blob: db310c8fd820f9361571c76a98f45b58f62f5455 [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 * */
Jan Pokornýbb654fe2016-04-13 16:56:07 +0200145 xmlDictPtr dict; /* the context dictionary */
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 *
Jan Pokornýbb654fe2016-04-13 16:56:07 +0200213 * Free a string if it is not owned by the "dict" dictionary in the
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000214 * 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
Daniel Veillard91309d32014-10-06 20:07:19 +0800289 if ((reader != NULL) && (reader->ctxt != NULL))
290 dict = reader->ctxt->dict;
291 else
292 dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000293 if (cur == NULL) return;
294
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000295 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
296 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
297
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000298 /* Check for ID removal -> leading to invalid references ! */
299 if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
300 ((cur->parent->doc->intSubset != NULL) ||
301 (cur->parent->doc->extSubset != NULL))) {
302 if (xmlIsID(cur->parent->doc, cur->parent, cur))
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000303 xmlTextReaderRemoveID(cur->parent->doc, cur);
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000304 }
305 if (cur->children != NULL)
306 xmlTextReaderFreeNodeList(reader, cur->children);
307
308 DICT_FREE(cur->name);
309 if ((reader != NULL) && (reader->ctxt != NULL) &&
310 (reader->ctxt->freeAttrsNr < 100)) {
311 cur->next = reader->ctxt->freeAttrs;
312 reader->ctxt->freeAttrs = cur;
313 reader->ctxt->freeAttrsNr++;
314 } else {
315 xmlFree(cur);
316 }
317}
318
319/**
320 * xmlTextReaderFreePropList:
321 * @reader: the xmlTextReaderPtr used
322 * @cur: the first property in the list
323 *
324 * Free a property and all its siblings, all the children are freed too.
325 */
326static void
327xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
328 xmlAttrPtr next;
Daniel Veillard91309d32014-10-06 20:07:19 +0800329
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000330 while (cur != NULL) {
331 next = cur->next;
332 xmlTextReaderFreeProp(reader, cur);
333 cur = next;
334 }
335}
336
337/**
338 * xmlTextReaderFreeNodeList:
339 * @reader: the xmlTextReaderPtr used
340 * @cur: the first node in the list
341 *
342 * Free a node and all its siblings, this is a recursive behaviour, all
343 * the children are freed too.
344 */
345static void
346xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
347 xmlNodePtr next;
348 xmlDictPtr dict;
349
Daniel Veillard91309d32014-10-06 20:07:19 +0800350 if ((reader != NULL) && (reader->ctxt != NULL))
351 dict = reader->ctxt->dict;
352 else
353 dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000354 if (cur == NULL) return;
355 if (cur->type == XML_NAMESPACE_DECL) {
356 xmlFreeNsList((xmlNsPtr) cur);
357 return;
358 }
359 if ((cur->type == XML_DOCUMENT_NODE) ||
360 (cur->type == XML_HTML_DOCUMENT_NODE)) {
361 xmlFreeDoc((xmlDocPtr) cur);
362 return;
363 }
364 while (cur != NULL) {
365 next = cur->next;
366 /* unroll to speed up freeing the document */
367 if (cur->type != XML_DTD_NODE) {
368
369 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000370 (cur->type != XML_ENTITY_REF_NODE)) {
371 if (cur->children->parent == cur)
372 xmlTextReaderFreeNodeList(reader, cur->children);
373 cur->children = NULL;
374 }
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000375
376 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
377 xmlDeregisterNodeDefaultValue(cur);
378
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000379 if (((cur->type == XML_ELEMENT_NODE) ||
380 (cur->type == XML_XINCLUDE_START) ||
381 (cur->type == XML_XINCLUDE_END)) &&
382 (cur->properties != NULL))
383 xmlTextReaderFreePropList(reader, cur->properties);
Daniel Veillard8874b942005-08-25 13:19:21 +0000384 if ((cur->content != (xmlChar *) &(cur->properties)) &&
385 (cur->type != XML_ELEMENT_NODE) &&
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000386 (cur->type != XML_XINCLUDE_START) &&
387 (cur->type != XML_XINCLUDE_END) &&
388 (cur->type != XML_ENTITY_REF_NODE)) {
389 DICT_FREE(cur->content);
390 }
391 if (((cur->type == XML_ELEMENT_NODE) ||
392 (cur->type == XML_XINCLUDE_START) ||
393 (cur->type == XML_XINCLUDE_END)) &&
394 (cur->nsDef != NULL))
395 xmlFreeNsList(cur->nsDef);
396
397 /*
398 * we don't free element names here they are interned now
399 */
400 if ((cur->type != XML_TEXT_NODE) &&
401 (cur->type != XML_COMMENT_NODE))
402 DICT_FREE(cur->name);
403 if (((cur->type == XML_ELEMENT_NODE) ||
404 (cur->type == XML_TEXT_NODE)) &&
405 (reader != NULL) && (reader->ctxt != NULL) &&
406 (reader->ctxt->freeElemsNr < 100)) {
407 cur->next = reader->ctxt->freeElems;
408 reader->ctxt->freeElems = cur;
409 reader->ctxt->freeElemsNr++;
410 } else {
411 xmlFree(cur);
412 }
413 }
414 cur = next;
415 }
416}
417
418/**
419 * xmlTextReaderFreeNode:
420 * @reader: the xmlTextReaderPtr used
421 * @cur: the node
422 *
423 * Free a node, this is a recursive behaviour, all the children are freed too.
424 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
425 */
426static void
427xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
428 xmlDictPtr dict;
429
Daniel Veillard91309d32014-10-06 20:07:19 +0800430 if ((reader != NULL) && (reader->ctxt != NULL))
431 dict = reader->ctxt->dict;
432 else
433 dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000434 if (cur->type == XML_DTD_NODE) {
435 xmlFreeDtd((xmlDtdPtr) cur);
436 return;
437 }
438 if (cur->type == XML_NAMESPACE_DECL) {
439 xmlFreeNs((xmlNsPtr) cur);
440 return;
441 }
442 if (cur->type == XML_ATTRIBUTE_NODE) {
443 xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
444 return;
445 }
446
447 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000448 (cur->type != XML_ENTITY_REF_NODE)) {
449 if (cur->children->parent == cur)
450 xmlTextReaderFreeNodeList(reader, cur->children);
451 cur->children = NULL;
452 }
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000453
454 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
455 xmlDeregisterNodeDefaultValue(cur);
456
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000457 if (((cur->type == XML_ELEMENT_NODE) ||
458 (cur->type == XML_XINCLUDE_START) ||
459 (cur->type == XML_XINCLUDE_END)) &&
460 (cur->properties != NULL))
461 xmlTextReaderFreePropList(reader, cur->properties);
Daniel Veillard8874b942005-08-25 13:19:21 +0000462 if ((cur->content != (xmlChar *) &(cur->properties)) &&
463 (cur->type != XML_ELEMENT_NODE) &&
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000464 (cur->type != XML_XINCLUDE_START) &&
465 (cur->type != XML_XINCLUDE_END) &&
466 (cur->type != XML_ENTITY_REF_NODE)) {
467 DICT_FREE(cur->content);
468 }
469 if (((cur->type == XML_ELEMENT_NODE) ||
470 (cur->type == XML_XINCLUDE_START) ||
471 (cur->type == XML_XINCLUDE_END)) &&
472 (cur->nsDef != NULL))
473 xmlFreeNsList(cur->nsDef);
474
475 /*
476 * we don't free names here they are interned now
477 */
478 if ((cur->type != XML_TEXT_NODE) &&
479 (cur->type != XML_COMMENT_NODE))
480 DICT_FREE(cur->name);
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000481
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000482 if (((cur->type == XML_ELEMENT_NODE) ||
483 (cur->type == XML_TEXT_NODE)) &&
484 (reader != NULL) && (reader->ctxt != NULL) &&
485 (reader->ctxt->freeElemsNr < 100)) {
486 cur->next = reader->ctxt->freeElems;
487 reader->ctxt->freeElems = cur;
488 reader->ctxt->freeElemsNr++;
489 } else {
490 xmlFree(cur);
491 }
492}
493
Nick Wellnhofere03f0a12017-11-09 16:42:47 +0100494static void
495xmlTextReaderFreeIDTableEntry(void *id, const xmlChar *name ATTRIBUTE_UNUSED) {
496 xmlFreeID((xmlIDPtr) id);
497}
498
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000499/**
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000500 * xmlTextReaderFreeIDTable:
501 * @table: An id table
502 *
503 * Deallocate the memory used by an ID hash table.
504 */
William M. Brack60f394e2003-11-16 06:25:42 +0000505static void
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000506xmlTextReaderFreeIDTable(xmlIDTablePtr table) {
Nick Wellnhofere03f0a12017-11-09 16:42:47 +0100507 xmlHashFree(table, xmlTextReaderFreeIDTableEntry);
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000508}
509
510/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000511 * xmlTextReaderFreeDoc:
512 * @reader: the xmlTextReaderPtr used
513 * @cur: pointer to the document
514 *
515 * Free up all the structures used by a document, tree included.
516 */
517static void
518xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
519 xmlDtdPtr extSubset, intSubset;
520
521 if (cur == NULL) return;
522
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000523 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
524 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
525
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000526 /*
527 * Do this before freeing the children list to avoid ID lookups
528 */
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000529 if (cur->ids != NULL) xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids);
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000530 cur->ids = NULL;
531 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
532 cur->refs = NULL;
533 extSubset = cur->extSubset;
534 intSubset = cur->intSubset;
535 if (intSubset == extSubset)
536 extSubset = NULL;
537 if (extSubset != NULL) {
538 xmlUnlinkNode((xmlNodePtr) cur->extSubset);
539 cur->extSubset = NULL;
540 xmlFreeDtd(extSubset);
541 }
542 if (intSubset != NULL) {
543 xmlUnlinkNode((xmlNodePtr) cur->intSubset);
544 cur->intSubset = NULL;
545 xmlFreeDtd(intSubset);
546 }
547
548 if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
549
550 if (cur->version != NULL) xmlFree((char *) cur->version);
551 if (cur->name != NULL) xmlFree((char *) cur->name);
552 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
553 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
554 if (cur->URL != NULL) xmlFree((char *) cur->URL);
Daniel Veillard500a1de2004-03-22 15:22:58 +0000555 if (cur->dict != NULL) xmlDictFree(cur->dict);
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000556
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000557 xmlFree(cur);
558}
559
560/************************************************************************
561 * *
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000562 * The reader core parser *
563 * *
564 ************************************************************************/
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000565#ifdef DEBUG_READER
566static void
567xmlTextReaderDebug(xmlTextReaderPtr reader) {
568 if ((reader == NULL) || (reader->ctxt == NULL)) {
569 fprintf(stderr, "xmlTextReader NULL\n");
570 return;
571 }
572 fprintf(stderr, "xmlTextReader: state %d depth %d ",
573 reader->state, reader->depth);
574 if (reader->node == NULL) {
575 fprintf(stderr, "node = NULL\n");
576 } else {
577 fprintf(stderr, "node %s\n", reader->node->name);
578 }
579 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
580 reader->base, reader->cur, reader->ctxt->nodeNr);
581 if (reader->input->buffer == NULL) {
582 fprintf(stderr, "buffer is NULL\n");
583 } else {
584#ifdef LIBXML_DEBUG_ENABLED
585 xmlDebugDumpString(stderr,
586 &reader->input->buffer->content[reader->cur]);
587#endif
588 fprintf(stderr, "\n");
589 }
590}
591#endif
592
593/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000594 * xmlTextReaderEntPush:
595 * @reader: the xmlTextReaderPtr used
596 * @value: the entity reference node
597 *
598 * Pushes a new entity reference node on top of the entities stack
599 *
600 * Returns 0 in case of error, the index in the stack otherwise
601 */
602static int
603xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
604{
605 if (reader->entMax <= 0) {
606 reader->entMax = 10;
607 reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
608 sizeof(reader->entTab[0]));
609 if (reader->entTab == NULL) {
610 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
611 return (0);
612 }
613 }
614 if (reader->entNr >= reader->entMax) {
615 reader->entMax *= 2;
616 reader->entTab =
617 (xmlNodePtr *) xmlRealloc(reader->entTab,
618 reader->entMax *
619 sizeof(reader->entTab[0]));
620 if (reader->entTab == NULL) {
621 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
622 return (0);
623 }
624 }
625 reader->entTab[reader->entNr] = value;
626 reader->ent = value;
627 return (reader->entNr++);
628}
629
630/**
631 * xmlTextReaderEntPop:
632 * @reader: the xmlTextReaderPtr used
633 *
634 * Pops the top element entity from the entities stack
635 *
636 * Returns the entity just removed
637 */
638static xmlNodePtr
639xmlTextReaderEntPop(xmlTextReaderPtr reader)
640{
641 xmlNodePtr ret;
642
643 if (reader->entNr <= 0)
Daniel Veillard75e389d2005-07-29 22:02:24 +0000644 return (NULL);
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000645 reader->entNr--;
646 if (reader->entNr > 0)
647 reader->ent = reader->entTab[reader->entNr - 1];
648 else
649 reader->ent = NULL;
650 ret = reader->entTab[reader->entNr];
Daniel Veillard75e389d2005-07-29 22:02:24 +0000651 reader->entTab[reader->entNr] = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000652 return (ret);
653}
654
655/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000656 * xmlTextReaderStartElement:
657 * @ctx: the user data (XML parser context)
658 * @fullname: The element name, including namespace prefix
659 * @atts: An array of name/value attributes pairs, NULL terminated
660 *
661 * called when an opening tag has been processed.
662 */
663static void
664xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
665 const xmlChar **atts) {
666 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
667 xmlTextReaderPtr reader = ctxt->_private;
668
669#ifdef DEBUG_CALLBACKS
670 printf("xmlTextReaderStartElement(%s)\n", fullname);
671#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000672 if ((reader != NULL) && (reader->startElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000673 reader->startElement(ctx, fullname, atts);
Daniel Veillard067bae52003-01-05 01:27:54 +0000674 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
675 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
676 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000677 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000678 }
Daniel Veillard9e395c22003-01-01 14:50:44 +0000679 if (reader != NULL)
680 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000681}
682
683/**
684 * xmlTextReaderEndElement:
685 * @ctx: the user data (XML parser context)
686 * @fullname: The element name, including namespace prefix
687 *
688 * called when an ending tag has been processed.
689 */
690static void
691xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
692 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
693 xmlTextReaderPtr reader = ctxt->_private;
694
695#ifdef DEBUG_CALLBACKS
696 printf("xmlTextReaderEndElement(%s)\n", fullname);
697#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000698 if ((reader != NULL) && (reader->endElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000699 reader->endElement(ctx, fullname);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000700 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000701}
702
703/**
Daniel Veillard07cb8222003-09-10 10:51:05 +0000704 * xmlTextReaderStartElementNs:
705 * @ctx: the user data (XML parser context)
706 * @localname: the local name of the element
707 * @prefix: the element namespace prefix if available
708 * @URI: the element namespace name if available
709 * @nb_namespaces: number of namespace definitions on that node
710 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
711 * @nb_attributes: the number of attributes on that node
712 * nb_defaulted: the number of defaulted attributes.
713 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
714 * attribute values.
715 *
716 * called when an opening tag has been processed.
717 */
718static void
719xmlTextReaderStartElementNs(void *ctx,
720 const xmlChar *localname,
721 const xmlChar *prefix,
722 const xmlChar *URI,
723 int nb_namespaces,
724 const xmlChar **namespaces,
725 int nb_attributes,
726 int nb_defaulted,
727 const xmlChar **attributes)
728{
729 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
730 xmlTextReaderPtr reader = ctxt->_private;
731
732#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000733 printf("xmlTextReaderStartElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000734#endif
735 if ((reader != NULL) && (reader->startElementNs != NULL)) {
736 reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
737 namespaces, nb_attributes, nb_defaulted,
738 attributes);
739 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
740 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
741 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000742 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillard07cb8222003-09-10 10:51:05 +0000743 }
744 if (reader != NULL)
745 reader->state = XML_TEXTREADER_ELEMENT;
746}
747
748/**
749 * xmlTextReaderEndElementNs:
750 * @ctx: the user data (XML parser context)
751 * @localname: the local name of the element
752 * @prefix: the element namespace prefix if available
753 * @URI: the element namespace name if available
754 *
755 * called when an ending tag has been processed.
756 */
757static void
758xmlTextReaderEndElementNs(void *ctx,
759 const xmlChar * localname,
760 const xmlChar * prefix,
761 const xmlChar * URI)
762{
763 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
764 xmlTextReaderPtr reader = ctxt->_private;
765
766#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000767 printf("xmlTextReaderEndElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000768#endif
769 if ((reader != NULL) && (reader->endElementNs != NULL)) {
770 reader->endElementNs(ctx, localname, prefix, URI);
771 }
772}
773
774
775/**
Daniel Veillardea7751d2002-12-20 00:16:24 +0000776 * xmlTextReaderCharacters:
777 * @ctx: the user data (XML parser context)
778 * @ch: a xmlChar string
779 * @len: the number of xmlChar
780 *
781 * receiving some chars from the parser.
782 */
783static void
784xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
785{
786 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
787 xmlTextReaderPtr reader = ctxt->_private;
788
789#ifdef DEBUG_CALLBACKS
790 printf("xmlTextReaderCharacters()\n");
791#endif
792 if ((reader != NULL) && (reader->characters != NULL)) {
793 reader->characters(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000794 }
795}
796
797/**
798 * xmlTextReaderCDataBlock:
799 * @ctx: the user data (XML parser context)
800 * @value: The pcdata content
801 * @len: the block length
802 *
803 * called when a pcdata block has been parsed
804 */
805static void
806xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
807{
808 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
809 xmlTextReaderPtr reader = ctxt->_private;
810
811#ifdef DEBUG_CALLBACKS
812 printf("xmlTextReaderCDataBlock()\n");
813#endif
814 if ((reader != NULL) && (reader->cdataBlock != NULL)) {
815 reader->cdataBlock(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000816 }
817}
818
819/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000820 * xmlTextReaderPushData:
821 * @reader: the xmlTextReaderPtr used
822 *
823 * Push data down the progressive parser until a significant callback
824 * got raised.
825 *
826 * Returns -1 in case of failure, 0 otherwise
827 */
828static int
829xmlTextReaderPushData(xmlTextReaderPtr reader) {
Daniel Veillard8aebce32012-07-16 14:42:31 +0800830 xmlBufPtr inbuf;
Daniel Veillarda880b122003-04-21 21:36:41 +0000831 int val, s;
William M. Brack779af002003-08-01 15:55:39 +0000832 xmlTextReaderState oldstate;
Daniel Veillard8aebce32012-07-16 14:42:31 +0800833 int alloc;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000834
835 if ((reader->input == NULL) || (reader->input->buffer == NULL))
836 return(-1);
837
Daniel Veillardea7751d2002-12-20 00:16:24 +0000838 oldstate = reader->state;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000839 reader->state = XML_TEXTREADER_NONE;
840 inbuf = reader->input->buffer;
Daniel Veillard8aebce32012-07-16 14:42:31 +0800841 alloc = xmlBufGetAllocationScheme(inbuf);
Daniel Veillarda880b122003-04-21 21:36:41 +0000842
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000843 while (reader->state == XML_TEXTREADER_NONE) {
Daniel Veillard8aebce32012-07-16 14:42:31 +0800844 if (xmlBufUse(inbuf) < reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000845 /*
846 * Refill the buffer unless we are at the end of the stream
847 */
848 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
849 val = xmlParserInputBufferRead(reader->input, 4096);
Daniel Veillard53350552003-09-18 13:35:51 +0000850 if ((val == 0) &&
Daniel Veillard8aebce32012-07-16 14:42:31 +0800851 (alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
852 if (xmlBufUse(inbuf) == reader->cur) {
Daniel Veillard53350552003-09-18 13:35:51 +0000853 reader->mode = XML_TEXTREADER_MODE_EOF;
854 reader->state = oldstate;
Daniel Veillard53350552003-09-18 13:35:51 +0000855 }
856 } else if (val < 0) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000857 reader->mode = XML_TEXTREADER_MODE_EOF;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000858 reader->state = oldstate;
Daniel Veillardaaa105b2002-12-30 11:42:17 +0000859 if ((oldstate != XML_TEXTREADER_START) ||
860 (reader->ctxt->myDoc != NULL))
861 return(val);
Daniel Veillard53350552003-09-18 13:35:51 +0000862 } else if (val == 0) {
863 /* mark the end of the stream and process the remains */
864 reader->mode = XML_TEXTREADER_MODE_EOF;
865 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000866 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000867
Daniel Veillardaacc2a22009-08-11 18:31:42 +0200868 } else
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000869 break;
870 }
Daniel Veillard067bae52003-01-05 01:27:54 +0000871 /*
Daniel Veillarda880b122003-04-21 21:36:41 +0000872 * parse by block of CHUNK_SIZE bytes, various tests show that
873 * it's the best tradeoff at least on a 1.2GH Duron
Daniel Veillard067bae52003-01-05 01:27:54 +0000874 */
Daniel Veillard8aebce32012-07-16 14:42:31 +0800875 if (xmlBufUse(inbuf) >= reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000876 val = xmlParseChunk(reader->ctxt,
Daniel Veillard8aebce32012-07-16 14:42:31 +0800877 (const char *) xmlBufContent(inbuf) + reader->cur,
878 CHUNK_SIZE, 0);
Daniel Veillarda880b122003-04-21 21:36:41 +0000879 reader->cur += CHUNK_SIZE;
Andy Lutomirski9d9685a2012-05-15 20:10:25 +0800880 if (val != 0)
881 reader->ctxt->wellFormed = 0;
882 if (reader->ctxt->wellFormed == 0)
883 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000884 } else {
Daniel Veillard8aebce32012-07-16 14:42:31 +0800885 s = xmlBufUse(inbuf) - reader->cur;
Daniel Veillarda880b122003-04-21 21:36:41 +0000886 val = xmlParseChunk(reader->ctxt,
Daniel Veillard8aebce32012-07-16 14:42:31 +0800887 (const char *) xmlBufContent(inbuf) + reader->cur,
888 s, 0);
Daniel Veillarda880b122003-04-21 21:36:41 +0000889 reader->cur += s;
Andy Lutomirski9d9685a2012-05-15 20:10:25 +0800890 if (val != 0)
891 reader->ctxt->wellFormed = 0;
Daniel Veillarda880b122003-04-21 21:36:41 +0000892 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000893 }
894 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000895
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000896 /*
897 * Discard the consumed input when needed and possible
898 */
Daniel Veillard67df8092002-12-16 22:04:11 +0000899 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
Daniel Veillard8aebce32012-07-16 14:42:31 +0800900 if (alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
Daniel Veillard21924522004-02-19 16:37:07 +0000901 if ((reader->cur >= 4096) &&
Daniel Veillard8aebce32012-07-16 14:42:31 +0800902 (xmlBufUse(inbuf) - reader->cur <= CHUNK_SIZE)) {
903 val = xmlBufShrink(inbuf, reader->cur);
Daniel Veillard21924522004-02-19 16:37:07 +0000904 if (val >= 0) {
905 reader->cur -= val;
906 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000907 }
908 }
909 }
910
911 /*
912 * At the end of the stream signal that the work is done to the Push
913 * parser.
914 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000915 else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
Daniel Veillarda9c56772007-03-09 16:59:05 +0000916 if (reader->state != XML_TEXTREADER_DONE) {
Daniel Veillard8aebce32012-07-16 14:42:31 +0800917 s = xmlBufUse(inbuf) - reader->cur;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000918 val = xmlParseChunk(reader->ctxt,
Daniel Veillard8aebce32012-07-16 14:42:31 +0800919 (const char *) xmlBufContent(inbuf) + reader->cur,
920 s, 1);
921 reader->cur = xmlBufUse(inbuf);
Daniel Veillarda9c56772007-03-09 16:59:05 +0000922 reader->state = XML_TEXTREADER_DONE;
Andy Lutomirski9d9685a2012-05-15 20:10:25 +0800923 if (val != 0) {
924 if (reader->ctxt->wellFormed)
925 reader->ctxt->wellFormed = 0;
926 else
927 return(-1);
928 }
Daniel Veillardea7751d2002-12-20 00:16:24 +0000929 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000930 }
Daniel Veillardea7751d2002-12-20 00:16:24 +0000931 reader->state = oldstate;
Daniel Veillardc508fa32012-07-18 17:39:56 +0800932 if (reader->ctxt->wellFormed == 0) {
Andy Lutomirski9d9685a2012-05-15 20:10:25 +0800933 reader->mode = XML_TEXTREADER_MODE_EOF;
Daniel Veillardc508fa32012-07-18 17:39:56 +0800934 return(-1);
935 }
936
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000937 return(0);
938}
939
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000940#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000941/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000942 * xmlTextReaderValidatePush:
943 * @reader: the xmlTextReaderPtr used
944 *
945 * Push the current node for validation
946 */
947static void
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000948xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000949 xmlNodePtr node = reader->node;
950
Daniel Veillardf54cd532004-02-25 11:52:31 +0000951#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000952 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
953 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
954 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
955 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
956 reader->ctxt->myDoc, node, node->name);
957 } else {
958 /* TODO use the BuildQName interface */
959 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000960
Daniel Veillardf4e55762003-04-15 23:32:22 +0000961 qname = xmlStrdup(node->ns->prefix);
962 qname = xmlStrcat(qname, BAD_CAST ":");
963 qname = xmlStrcat(qname, node->name);
964 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
965 reader->ctxt->myDoc, node, qname);
966 if (qname != NULL)
967 xmlFree(qname);
968 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000969 }
970#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000971#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +0000972 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +0000973 (reader->rngValidCtxt != NULL)) {
974 int ret;
975
976 if (reader->rngFullNode != NULL) return;
977 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
978 reader->ctxt->myDoc,
979 node);
980 if (ret == 0) {
981 /*
982 * this element requires a full tree
983 */
984 node = xmlTextReaderExpand(reader);
985 if (node == NULL) {
986printf("Expand failed !\n");
987 ret = -1;
988 } else {
989 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
990 reader->ctxt->myDoc,
991 node);
992 reader->rngFullNode = node;
993 }
994 }
995 if (ret != 1)
996 reader->rngValidErrors++;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000997 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000998#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000999}
Daniel Veillardf4e55762003-04-15 23:32:22 +00001000
1001/**
1002 * xmlTextReaderValidateCData:
1003 * @reader: the xmlTextReaderPtr used
1004 * @data: pointer to the CData
Michael Woodfb27e2c2012-09-28 08:59:33 +02001005 * @len: length of the CData block in bytes.
Daniel Veillardf4e55762003-04-15 23:32:22 +00001006 *
1007 * Push some CData for validation
1008 */
1009static void
1010xmlTextReaderValidateCData(xmlTextReaderPtr reader,
1011 const xmlChar *data, int len) {
Daniel Veillardf54cd532004-02-25 11:52:31 +00001012#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001013 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
1014 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
1015 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
1016 data, len);
Daniel Veillardf54cd532004-02-25 11:52:31 +00001017 }
1018#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +00001019#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +00001020 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001021 (reader->rngValidCtxt != NULL)) {
1022 int ret;
1023
1024 if (reader->rngFullNode != NULL) return;
1025 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
1026 if (ret != 1)
1027 reader->rngValidErrors++;
Daniel Veillardf4e55762003-04-15 23:32:22 +00001028 }
Daniel Veillardf54cd532004-02-25 11:52:31 +00001029#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00001030}
1031
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001032/**
1033 * xmlTextReaderValidatePop:
1034 * @reader: the xmlTextReaderPtr used
1035 *
1036 * Pop the current node from validation
1037 */
1038static void
1039xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
1040 xmlNodePtr node = reader->node;
1041
Daniel Veillardf54cd532004-02-25 11:52:31 +00001042#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001043 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
1044 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
1045 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
1046 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
1047 reader->ctxt->myDoc, node, node->name);
1048 } else {
1049 /* TODO use the BuildQName interface */
1050 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001051
Daniel Veillardf4e55762003-04-15 23:32:22 +00001052 qname = xmlStrdup(node->ns->prefix);
1053 qname = xmlStrcat(qname, BAD_CAST ":");
1054 qname = xmlStrcat(qname, node->name);
1055 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
1056 reader->ctxt->myDoc, node, qname);
1057 if (qname != NULL)
1058 xmlFree(qname);
1059 }
Daniel Veillardf54cd532004-02-25 11:52:31 +00001060 }
1061#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +00001062#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +00001063 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001064 (reader->rngValidCtxt != NULL)) {
1065 int ret;
1066
1067 if (reader->rngFullNode != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001068 if (node == reader->rngFullNode)
Daniel Veillardf4e55762003-04-15 23:32:22 +00001069 reader->rngFullNode = NULL;
1070 return;
1071 }
1072 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
1073 reader->ctxt->myDoc,
1074 node);
1075 if (ret != 1)
1076 reader->rngValidErrors++;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001077 }
Daniel Veillardf54cd532004-02-25 11:52:31 +00001078#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001079}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001080
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001081/**
1082 * xmlTextReaderValidateEntity:
1083 * @reader: the xmlTextReaderPtr used
1084 *
1085 * Handle the validation when an entity reference is encountered and
1086 * entity substitution is not activated. As a result the parser interface
1087 * must walk through the entity and do the validation calls
1088 */
1089static void
1090xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
1091 xmlNodePtr oldnode = reader->node;
1092 xmlNodePtr node = reader->node;
1093 xmlParserCtxtPtr ctxt = reader->ctxt;
1094
1095 do {
1096 if (node->type == XML_ENTITY_REF_NODE) {
1097 /*
1098 * Case where the underlying tree is not availble, lookup the entity
1099 * and walk it.
1100 */
1101 if ((node->children == NULL) && (ctxt->sax != NULL) &&
1102 (ctxt->sax->getEntity != NULL)) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001103 node->children = (xmlNodePtr)
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001104 ctxt->sax->getEntity(ctxt, node->name);
1105 }
1106
1107 if ((node->children != NULL) &&
1108 (node->children->type == XML_ENTITY_DECL) &&
1109 (node->children->children != NULL)) {
1110 xmlTextReaderEntPush(reader, node);
1111 node = node->children->children;
1112 continue;
1113 } else {
1114 /*
1115 * The error has probably be raised already.
1116 */
1117 if (node == oldnode)
1118 break;
1119 node = node->next;
1120 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001121#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001122 } else if (node->type == XML_ELEMENT_NODE) {
1123 reader->node = node;
1124 xmlTextReaderValidatePush(reader);
1125 } else if ((node->type == XML_TEXT_NODE) ||
1126 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001127 xmlTextReaderValidateCData(reader, node->content,
1128 xmlStrlen(node->content));
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001129#endif
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001130 }
1131
1132 /*
1133 * go to next node
1134 */
1135 if (node->children != NULL) {
1136 node = node->children;
1137 continue;
Daniel Veillardef8dd7b2003-03-23 12:02:56 +00001138 } else if (node->type == XML_ELEMENT_NODE) {
1139 xmlTextReaderValidatePop(reader);
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001140 }
1141 if (node->next != NULL) {
1142 node = node->next;
1143 continue;
1144 }
1145 do {
1146 node = node->parent;
1147 if (node->type == XML_ELEMENT_NODE) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001148 xmlNodePtr tmp;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001149 if (reader->entNr == 0) {
1150 while ((tmp = node->last) != NULL) {
Daniel Veillarde8039df2003-10-27 11:25:13 +00001151 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001152 xmlUnlinkNode(tmp);
1153 xmlTextReaderFreeNode(reader, tmp);
1154 } else
1155 break;
1156 }
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001157 }
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001158 reader->node = node;
1159 xmlTextReaderValidatePop(reader);
1160 }
1161 if ((node->type == XML_ENTITY_DECL) &&
1162 (reader->ent != NULL) && (reader->ent->children == node)) {
1163 node = xmlTextReaderEntPop(reader);
1164 }
1165 if (node == oldnode)
1166 break;
1167 if (node->next != NULL) {
1168 node = node->next;
1169 break;
1170 }
1171 } while ((node != NULL) && (node != oldnode));
1172 } while ((node != NULL) && (node != oldnode));
1173 reader->node = oldnode;
1174}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001175#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001176
1177
1178/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001179 * xmlTextReaderGetSuccessor:
1180 * @cur: the current node
1181 *
1182 * Get the successor of a node if available.
1183 *
1184 * Returns the successor node or NULL
1185 */
1186static xmlNodePtr
1187xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1188 if (cur == NULL) return(NULL) ; /* ERROR */
1189 if (cur->next != NULL) return(cur->next) ;
1190 do {
1191 cur = cur->parent;
Daniel Veillard11ce4002006-03-10 00:36:23 +00001192 if (cur == NULL) break;
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001193 if (cur->next != NULL) return(cur->next);
1194 } while (cur != NULL);
1195 return(cur);
1196}
1197
1198/**
1199 * xmlTextReaderDoExpand:
1200 * @reader: the xmlTextReaderPtr used
1201 *
1202 * Makes sure that the current node is fully read as well as all its
1203 * descendant. It means the full DOM subtree must be available at the
1204 * end of the call.
1205 *
1206 * Returns 1 if the node was expanded successfully, 0 if there is no more
1207 * nodes to read, or -1 in case of error
1208 */
1209static int
1210xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1211 int val;
1212
1213 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1214 return(-1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001215 do {
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001216 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1217
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001218 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1219 return(1);
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001220 if (reader->ctxt->nodeNr < reader->depth)
Daniel Veillarda37aab82003-06-09 09:10:36 +00001221 return(1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001222 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1223 return(1);
1224 val = xmlTextReaderPushData(reader);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001225 if (val < 0){
William M. Brack0c1e3012007-03-14 12:40:21 +00001226 reader->mode = XML_TEXTREADER_MODE_ERROR;
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001227 return(-1);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001228 }
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001229 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1230 return(1);
1231}
1232
1233/**
Daniel Veillarde125b312005-01-28 17:39:49 +00001234 * xmlTextReaderCollectSiblings:
1235 * @node: the first child
1236 *
1237 * Traverse depth-first through all sibling nodes and their children
1238 * nodes and concatenate their content. This is an auxiliary function
1239 * to xmlTextReaderReadString.
1240 *
1241 * Returns a string containing the content, or NULL in case of error.
1242 */
1243static xmlChar *
1244xmlTextReaderCollectSiblings(xmlNodePtr node)
1245{
1246 xmlBufferPtr buffer;
1247 xmlChar *ret;
1248
Daniel Veillard3e62adb2012-08-09 14:24:02 +08001249 if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
1250 return(NULL);
1251
Daniel Veillarde125b312005-01-28 17:39:49 +00001252 buffer = xmlBufferCreate();
1253 if (buffer == NULL)
1254 return NULL;
1255
1256 for ( ; node != NULL; node = node->next) {
1257 switch (node->type) {
1258 case XML_TEXT_NODE:
1259 case XML_CDATA_SECTION_NODE:
1260 xmlBufferCat(buffer, node->content);
1261 break;
Daniel Veillard47fffb42005-09-22 11:14:43 +00001262 case XML_ELEMENT_NODE: {
1263 xmlChar *tmp;
1264
1265 tmp = xmlTextReaderCollectSiblings(node->children);
1266 xmlBufferCat(buffer, tmp);
1267 xmlFree(tmp);
1268 break;
1269 }
Daniel Veillarde125b312005-01-28 17:39:49 +00001270 default:
1271 break;
1272 }
1273 }
1274 ret = buffer->content;
1275 buffer->content = NULL;
1276 xmlBufferFree(buffer);
1277 return(ret);
1278}
1279
1280/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001281 * xmlTextReaderRead:
1282 * @reader: the xmlTextReaderPtr used
1283 *
1284 * Moves the position of the current instance to the next node in
1285 * the stream, exposing its properties.
1286 *
1287 * Returns 1 if the node was read successfully, 0 if there is no more
1288 * nodes to read, or -1 in case of error
1289 */
1290int
1291xmlTextReaderRead(xmlTextReaderPtr reader) {
Daniel Veillard067bae52003-01-05 01:27:54 +00001292 int val, olddepth = 0;
William M. Brack899e64a2003-09-26 18:03:42 +00001293 xmlTextReaderState oldstate = XML_TEXTREADER_START;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001294 xmlNodePtr oldnode = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001295
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001296
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001297 if (reader == NULL)
1298 return(-1);
William M. Brack1af55582004-07-22 17:18:00 +00001299 reader->curnode = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001300 if (reader->doc != NULL)
1301 return(xmlTextReaderReadTree(reader));
1302 if (reader->ctxt == NULL)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001303 return(-1);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001304
1305#ifdef DEBUG_READER
1306 fprintf(stderr, "\nREAD ");
1307 DUMP_READER
1308#endif
Daniel Veillard67df8092002-12-16 22:04:11 +00001309 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1310 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001311 /*
1312 * Initial state
1313 */
1314 do {
1315 val = xmlTextReaderPushData(reader);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001316 if (val < 0){
1317 reader->mode = XML_TEXTREADER_MODE_ERROR;
1318 reader->state = XML_TEXTREADER_ERROR;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001319 return(-1);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001320 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001321 } while ((reader->ctxt->node == NULL) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001322 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
Daniel Veillarda9c56772007-03-09 16:59:05 +00001323 (reader->state != XML_TEXTREADER_DONE)));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001324 if (reader->ctxt->node == NULL) {
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001325 if (reader->ctxt->myDoc != NULL) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001326 reader->node = reader->ctxt->myDoc->children;
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001327 }
Daniel Veillarda9c56772007-03-09 16:59:05 +00001328 if (reader->node == NULL){
1329 reader->mode = XML_TEXTREADER_MODE_ERROR;
1330 reader->state = XML_TEXTREADER_ERROR;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001331 return(-1);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001332 }
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001333 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001334 } else {
Daniel Veillard48ef4c92003-03-22 12:38:15 +00001335 if (reader->ctxt->myDoc != NULL) {
1336 reader->node = reader->ctxt->myDoc->children;
1337 }
1338 if (reader->node == NULL)
1339 reader->node = reader->ctxt->nodeTab[0];
Daniel Veillarde59494f2003-01-04 16:35:29 +00001340 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001341 }
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001342 reader->depth = 0;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00001343 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001344 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001345 }
1346 oldstate = reader->state;
1347 olddepth = reader->ctxt->nodeNr;
1348 oldnode = reader->node;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001349
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001350get_next_node:
Daniel Veillard6f379a72004-04-29 18:45:42 +00001351 if (reader->node == NULL) {
Daniel Veillarda9c56772007-03-09 16:59:05 +00001352 if (reader->mode == XML_TEXTREADER_MODE_EOF)
Daniel Veillard6f379a72004-04-29 18:45:42 +00001353 return(0);
1354 else
1355 return(-1);
1356 }
Daniel Veillarde2161a62004-04-29 17:14:25 +00001357
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001358 /*
1359 * If we are not backtracking on ancestors or examined nodes,
1360 * that the parser didn't finished or that we arent at the end
1361 * of stream, continue processing.
1362 */
Daniel Veillarde2161a62004-04-29 17:14:25 +00001363 while ((reader->node != NULL) && (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001364 (reader->ctxt->nodeNr == olddepth) &&
1365 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
Daniel Veillardea7751d2002-12-20 00:16:24 +00001366 (reader->node->children == NULL) ||
1367 (reader->node->type == XML_ENTITY_REF_NODE) ||
Daniel Veillard409a8142003-07-18 15:16:57 +00001368 ((reader->node->children != NULL) &&
1369 (reader->node->children->type == XML_TEXT_NODE) &&
1370 (reader->node->children->next == NULL)) ||
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001371 (reader->node->type == XML_DTD_NODE) ||
1372 (reader->node->type == XML_DOCUMENT_NODE) ||
1373 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001374 ((reader->ctxt->node == NULL) ||
1375 (reader->ctxt->node == reader->node) ||
1376 (reader->ctxt->node == reader->node->parent)) &&
Daniel Veillardea7751d2002-12-20 00:16:24 +00001377 (reader->ctxt->instate != XML_PARSER_EOF)) {
1378 val = xmlTextReaderPushData(reader);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001379 if (val < 0){
1380 reader->mode = XML_TEXTREADER_MODE_ERROR;
1381 reader->state = XML_TEXTREADER_ERROR;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001382 return(-1);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001383 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001384 if (reader->node == NULL)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001385 goto node_end;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001386 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001387 if (oldstate != XML_TEXTREADER_BACKTRACK) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001388 if ((reader->node->children != NULL) &&
1389 (reader->node->type != XML_ENTITY_REF_NODE) &&
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001390 (reader->node->type != XML_XINCLUDE_START) &&
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001391 (reader->node->type != XML_DTD_NODE)) {
1392 reader->node = reader->node->children;
1393 reader->depth++;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001394 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001395 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001396 }
1397 }
1398 if (reader->node->next != NULL) {
1399 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillarddf512f42002-12-23 15:56:21 +00001400 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001401 (reader->node->children == NULL) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001402 ((reader->node->extra & NODE_IS_EMPTY) == 0)
1403#ifdef LIBXML_XINCLUDE_ENABLED
1404 && (reader->in_xinclude <= 0)
1405#endif
1406 ) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001407 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001408 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001409 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001410#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001411 if ((reader->validate) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001412 (reader->node->type == XML_ELEMENT_NODE))
1413 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001414#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001415 if ((reader->preserves > 0) &&
1416 (reader->node->extra & NODE_IS_SPRESERVED))
1417 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001418 reader->node = reader->node->next;
1419 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001420
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001421 /*
1422 * Cleanup of the old node
1423 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001424 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001425#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001426 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001427#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001428 (reader->entNr == 0) &&
1429 (reader->node->prev != NULL) &&
Daniel Veillardeea38152013-01-28 16:55:30 +01001430 (reader->node->prev->type != XML_DTD_NODE)) {
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001431 xmlNodePtr tmp = reader->node->prev;
Daniel Veillarde8039df2003-10-27 11:25:13 +00001432 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001433 xmlUnlinkNode(tmp);
1434 xmlTextReaderFreeNode(reader, tmp);
1435 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001436 }
1437
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001438 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001439 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001440 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillard571b8892002-12-30 12:37:59 +00001441 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001442 (reader->node->children == NULL) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001443 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001444 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001445 goto node_found;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001446 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001447#ifdef LIBXML_REGEXP_ENABLED
Gaurav Guptad319eb92014-10-06 12:24:17 +08001448 if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node->type == XML_ELEMENT_NODE))
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001449 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001450#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001451 if ((reader->preserves > 0) &&
1452 (reader->node->extra & NODE_IS_SPRESERVED))
1453 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001454 reader->node = reader->node->parent;
1455 if ((reader->node == NULL) ||
1456 (reader->node->type == XML_DOCUMENT_NODE) ||
1457#ifdef LIBXML_DOCB_ENABLED
1458 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1459#endif
1460 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillarda9c56772007-03-09 16:59:05 +00001461 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001462 val = xmlParseChunk(reader->ctxt, "", 0, 1);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001463 reader->state = XML_TEXTREADER_DONE;
William M. Brack9f797ab2004-07-28 07:40:12 +00001464 if (val != 0)
1465 return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +00001466 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001467 reader->node = NULL;
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001468 reader->depth = -1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001469
1470 /*
1471 * Cleanup of the old node
1472 */
Daniel Veillard76d36452009-09-07 11:19:33 +02001473 if ((oldnode != NULL) && (reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001474#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001475 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001476#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001477 (reader->entNr == 0) &&
1478 (oldnode->type != XML_DTD_NODE) &&
Daniel Veillardeea38152013-01-28 16:55:30 +01001479 ((oldnode->extra & NODE_IS_PRESERVED) == 0)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001480 xmlUnlinkNode(oldnode);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001481 xmlTextReaderFreeNode(reader, oldnode);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001482 }
1483
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001484 goto node_end;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001485 }
Daniel Veillard1e906612003-12-05 14:57:46 +00001486 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001487#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001488 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001489#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001490 (reader->entNr == 0) &&
1491 (reader->node->last != NULL) &&
1492 ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1493 xmlNodePtr tmp = reader->node->last;
1494 xmlUnlinkNode(tmp);
1495 xmlTextReaderFreeNode(reader, tmp);
1496 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001497 reader->depth--;
1498 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001499
1500node_found:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001501 DUMP_READER
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001502
1503 /*
Daniel Veillarda880b122003-04-21 21:36:41 +00001504 * If we are in the middle of a piece of CDATA make sure it's finished
1505 */
1506 if ((reader->node != NULL) &&
Daniel Veillardccc4d2b2003-09-17 21:27:31 +00001507 (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001508 ((reader->node->type == XML_TEXT_NODE) ||
1509 (reader->node->type == XML_CDATA_SECTION_NODE))) {
William M. Brack42331a92004-07-29 07:07:16 +00001510 if (xmlTextReaderExpand(reader) == NULL)
1511 return -1;
Daniel Veillarda880b122003-04-21 21:36:41 +00001512 }
1513
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001514#ifdef LIBXML_XINCLUDE_ENABLED
1515 /*
1516 * Handle XInclude if asked for
1517 */
1518 if ((reader->xinclude) && (reader->node != NULL) &&
1519 (reader->node->type == XML_ELEMENT_NODE) &&
1520 (reader->node->ns != NULL) &&
Daniel Veillardb5fa0202003-12-08 17:41:29 +00001521 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1522 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001523 if (reader->xincctxt == NULL) {
1524 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001525 xmlXIncludeSetFlags(reader->xincctxt,
Daniel Veillardc14c3892004-08-16 12:34:50 +00001526 reader->parserFlags & (~XML_PARSE_NOXINCNODE));
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001527 }
1528 /*
1529 * expand that node and process it
1530 */
William M. Brack42331a92004-07-29 07:07:16 +00001531 if (xmlTextReaderExpand(reader) == NULL)
1532 return -1;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001533 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1534 }
Daniel Veillard11ce4002006-03-10 00:36:23 +00001535 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_START)) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001536 reader->in_xinclude++;
1537 goto get_next_node;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001538 }
Daniel Veillard11ce4002006-03-10 00:36:23 +00001539 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_END)) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001540 reader->in_xinclude--;
1541 goto get_next_node;
1542 }
1543#endif
Daniel Veillarda880b122003-04-21 21:36:41 +00001544 /*
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001545 * Handle entities enter and exit when in entity replacement mode
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001546 */
1547 if ((reader->node != NULL) &&
1548 (reader->node->type == XML_ENTITY_REF_NODE) &&
1549 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1550 /*
1551 * Case where the underlying tree is not availble, lookup the entity
1552 * and walk it.
1553 */
1554 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1555 (reader->ctxt->sax->getEntity != NULL)) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001556 reader->node->children = (xmlNodePtr)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001557 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1558 }
1559
1560 if ((reader->node->children != NULL) &&
1561 (reader->node->children->type == XML_ENTITY_DECL) &&
1562 (reader->node->children->children != NULL)) {
1563 xmlTextReaderEntPush(reader, reader->node);
1564 reader->node = reader->node->children->children;
1565 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001566#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001567 } else if ((reader->node != NULL) &&
1568 (reader->node->type == XML_ENTITY_REF_NODE) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001569 (reader->ctxt != NULL) && (reader->validate)) {
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001570 xmlTextReaderValidateEntity(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001571#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001572 }
1573 if ((reader->node != NULL) &&
1574 (reader->node->type == XML_ENTITY_DECL) &&
1575 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1576 reader->node = xmlTextReaderEntPop(reader);
1577 reader->depth++;
1578 goto get_next_node;
1579 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001580#ifdef LIBXML_REGEXP_ENABLED
Gaurav Guptad319eb92014-10-06 12:24:17 +08001581 if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node != NULL)) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001582 xmlNodePtr node = reader->node;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001583
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001584 if ((node->type == XML_ELEMENT_NODE) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001585 ((reader->state != XML_TEXTREADER_END) &&
1586 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1587 xmlTextReaderValidatePush(reader);
1588 } else if ((node->type == XML_TEXT_NODE) ||
1589 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001590 xmlTextReaderValidateCData(reader, node->content,
1591 xmlStrlen(node->content));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001592 }
1593 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001594#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001595#ifdef LIBXML_PATTERN_ENABLED
1596 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1597 (reader->state != XML_TEXTREADER_BACKTRACK)) {
1598 int i;
1599 for (i = 0;i < reader->patternNr;i++) {
1600 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1601 xmlTextReaderPreserve(reader);
1602 break;
1603 }
1604 }
1605 }
1606#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillardf10ae122005-07-10 19:03:16 +00001607#ifdef LIBXML_SCHEMAS_ENABLED
1608 if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) &&
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001609 (reader->xsdValidErrors == 0) &&
Daniel Veillardf10ae122005-07-10 19:03:16 +00001610 (reader->xsdValidCtxt != NULL)) {
1611 reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt);
1612 }
1613#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001614 return(1);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001615node_end:
Daniel Veillarda9c56772007-03-09 16:59:05 +00001616 reader->state = XML_TEXTREADER_DONE;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001617 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001618}
1619
Daniel Veillard67df8092002-12-16 22:04:11 +00001620/**
1621 * xmlTextReaderReadState:
1622 * @reader: the xmlTextReaderPtr used
1623 *
1624 * Gets the read state of the reader.
1625 *
1626 * Returns the state value, or -1 in case of error
1627 */
1628int
1629xmlTextReaderReadState(xmlTextReaderPtr reader) {
1630 if (reader == NULL)
1631 return(-1);
1632 return(reader->mode);
1633}
1634
1635/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001636 * xmlTextReaderExpand:
1637 * @reader: the xmlTextReaderPtr used
1638 *
1639 * Reads the contents of the current node and the full subtree. It then makes
Daniel Veillard61c52202003-04-30 12:20:34 +00001640 * the subtree available until the next xmlTextReaderRead() call
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001641 *
1642 * Returns a node pointer valid until the next xmlTextReaderRead() call
1643 * or NULL in case of error.
1644 */
1645xmlNodePtr
1646xmlTextReaderExpand(xmlTextReaderPtr reader) {
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001647 if ((reader == NULL) || (reader->node == NULL))
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001648 return(NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001649 if (reader->doc != NULL)
1650 return(reader->node);
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001651 if (reader->ctxt == NULL)
1652 return(NULL);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001653 if (xmlTextReaderDoExpand(reader) < 0)
1654 return(NULL);
1655 return(reader->node);
1656}
1657
1658/**
1659 * xmlTextReaderNext:
1660 * @reader: the xmlTextReaderPtr used
1661 *
1662 * Skip to the node following the current one in document order while
1663 * avoiding the subtree if any.
1664 *
1665 * Returns 1 if the node was read successfully, 0 if there is no more
1666 * nodes to read, or -1 in case of error
1667 */
1668int
1669xmlTextReaderNext(xmlTextReaderPtr reader) {
1670 int ret;
1671 xmlNodePtr cur;
1672
1673 if (reader == NULL)
1674 return(-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001675 if (reader->doc != NULL)
1676 return(xmlTextReaderNextTree(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001677 cur = reader->node;
1678 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1679 return(xmlTextReaderRead(reader));
Daniel Veillard5963aa72005-03-10 12:23:24 +00001680 if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001681 return(xmlTextReaderRead(reader));
Daniel Veillarde8039df2003-10-27 11:25:13 +00001682 if (cur->extra & NODE_IS_EMPTY)
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001683 return(xmlTextReaderRead(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001684 do {
1685 ret = xmlTextReaderRead(reader);
1686 if (ret != 1)
1687 return(ret);
1688 } while (reader->node != cur);
1689 return(xmlTextReaderRead(reader));
1690}
1691
Daniel Veillardd0271472006-01-02 10:22:02 +00001692#ifdef LIBXML_WRITER_ENABLED
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001693/**
Daniel Veillard67df8092002-12-16 22:04:11 +00001694 * xmlTextReaderReadInnerXml:
1695 * @reader: the xmlTextReaderPtr used
1696 *
1697 * Reads the contents of the current node, including child nodes and markup.
1698 *
1699 * Returns a string containing the XML content, or NULL if the current node
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001700 * is neither an element nor attribute, or has no child nodes. The
Daniel Veillard67df8092002-12-16 22:04:11 +00001701 * string must be deallocated by the caller.
1702 */
1703xmlChar *
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001704xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1705{
1706 xmlChar *resbuf;
1707 xmlNodePtr node, cur_node;
1708 xmlBufferPtr buff, buff2;
1709 xmlDocPtr doc;
1710
1711 if (xmlTextReaderExpand(reader) == NULL) {
1712 return NULL;
1713 }
Elliott Hughes7fbecab2019-01-10 16:42:03 -08001714 doc = reader->node->doc;
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001715 buff = xmlBufferCreate();
1716 for (cur_node = reader->node->children; cur_node != NULL;
1717 cur_node = cur_node->next) {
Elliott Hughes7fbecab2019-01-10 16:42:03 -08001718 /* XXX: Why is the node copied? */
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001719 node = xmlDocCopyNode(cur_node, doc, 1);
1720 buff2 = xmlBufferCreate();
1721 if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
1722 xmlFreeNode(node);
1723 xmlBufferFree(buff2);
1724 xmlBufferFree(buff);
1725 return NULL;
1726 }
1727 xmlBufferCat(buff, buff2->content);
1728 xmlFreeNode(node);
1729 xmlBufferFree(buff2);
1730 }
1731 resbuf = buff->content;
Daniel Veillardbc4cc9d2005-12-12 13:26:56 +00001732 buff->content = NULL;
1733
1734 xmlBufferFree(buff);
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001735 return resbuf;
Daniel Veillard67df8092002-12-16 22:04:11 +00001736}
Daniel Veillardd0271472006-01-02 10:22:02 +00001737#endif
Daniel Veillard67df8092002-12-16 22:04:11 +00001738
Daniel Veillardd0271472006-01-02 10:22:02 +00001739#ifdef LIBXML_WRITER_ENABLED
Daniel Veillard67df8092002-12-16 22:04:11 +00001740/**
1741 * xmlTextReaderReadOuterXml:
1742 * @reader: the xmlTextReaderPtr used
1743 *
1744 * Reads the contents of the current node, including child nodes and markup.
1745 *
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001746 * Returns a string containing the node and any XML content, or NULL if the
1747 * current node cannot be serialized. The string must be deallocated
Rob Richards5b9dde32010-05-05 07:59:44 -04001748 * by the caller.
Daniel Veillard67df8092002-12-16 22:04:11 +00001749 */
1750xmlChar *
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001751xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1752{
1753 xmlChar *resbuf;
1754 xmlNodePtr node;
1755 xmlBufferPtr buff;
1756 xmlDocPtr doc;
1757
1758 node = reader->node;
Elliott Hughes7fbecab2019-01-10 16:42:03 -08001759 doc = node->doc;
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001760 if (xmlTextReaderExpand(reader) == NULL) {
1761 return NULL;
1762 }
Elliott Hughes7fbecab2019-01-10 16:42:03 -08001763 /* XXX: Why is the node copied? */
Rob Richards5b9dde32010-05-05 07:59:44 -04001764 if (node->type == XML_DTD_NODE) {
1765 node = (xmlNodePtr) xmlCopyDtd((xmlDtdPtr) node);
1766 } else {
1767 node = xmlDocCopyNode(node, doc, 1);
1768 }
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001769 buff = xmlBufferCreate();
1770 if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
1771 xmlFreeNode(node);
1772 xmlBufferFree(buff);
1773 return NULL;
1774 }
1775
1776 resbuf = buff->content;
1777 buff->content = NULL;
1778
1779 xmlFreeNode(node);
1780 xmlBufferFree(buff);
1781 return resbuf;
Daniel Veillard67df8092002-12-16 22:04:11 +00001782}
Daniel Veillardd0271472006-01-02 10:22:02 +00001783#endif
Daniel Veillard67df8092002-12-16 22:04:11 +00001784
1785/**
1786 * xmlTextReaderReadString:
1787 * @reader: the xmlTextReaderPtr used
1788 *
1789 * Reads the contents of an element or a text node as a string.
1790 *
1791 * Returns a string containing the contents of the Element or Text node,
1792 * or NULL if the reader is positioned on any other type of node.
1793 * The string must be deallocated by the caller.
1794 */
1795xmlChar *
Daniel Veillarde125b312005-01-28 17:39:49 +00001796xmlTextReaderReadString(xmlTextReaderPtr reader)
1797{
1798 xmlNodePtr node;
1799
1800 if ((reader == NULL) || (reader->node == NULL))
1801 return(NULL);
1802
1803 node = (reader->curnode != NULL) ? reader->curnode : reader->node;
1804 switch (node->type) {
1805 case XML_TEXT_NODE:
1806 if (node->content != NULL)
1807 return(xmlStrdup(node->content));
1808 break;
1809 case XML_ELEMENT_NODE:
1810 if (xmlTextReaderDoExpand(reader) != -1) {
1811 return xmlTextReaderCollectSiblings(node->children);
1812 }
Gaurav Guptad319eb92014-10-06 12:24:17 +08001813 break;
Daniel Veillarde125b312005-01-28 17:39:49 +00001814 case XML_ATTRIBUTE_NODE:
1815 TODO
1816 break;
1817 default:
1818 break;
1819 }
Daniel Veillard67df8092002-12-16 22:04:11 +00001820 return(NULL);
1821}
1822
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001823#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001824/**
1825 * xmlTextReaderReadBase64:
1826 * @reader: the xmlTextReaderPtr used
1827 * @array: a byte array to store the content.
1828 * @offset: the zero-based index into array where the method should
1829 * begin to write.
1830 * @len: the number of bytes to write.
1831 *
1832 * Reads and decodes the Base64 encoded contents of an element and
1833 * stores the result in a byte buffer.
1834 *
1835 * Returns the number of bytes written to array, or zero if the current
1836 * instance is not positioned on an element or -1 in case of error.
1837 */
1838int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001839xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1840 unsigned char *array ATTRIBUTE_UNUSED,
1841 int offset ATTRIBUTE_UNUSED,
1842 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001843 if ((reader == NULL) || (reader->ctxt == NULL))
1844 return(-1);
1845 if (reader->ctxt->wellFormed != 1)
1846 return(-1);
1847
1848 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1849 return(0);
1850 TODO
1851 return(0);
1852}
1853
1854/**
1855 * xmlTextReaderReadBinHex:
1856 * @reader: the xmlTextReaderPtr used
1857 * @array: a byte array to store the content.
1858 * @offset: the zero-based index into array where the method should
1859 * begin to write.
1860 * @len: the number of bytes to write.
1861 *
1862 * Reads and decodes the BinHex encoded contents of an element and
1863 * stores the result in a byte buffer.
1864 *
1865 * Returns the number of bytes written to array, or zero if the current
1866 * instance is not positioned on an element or -1 in case of error.
1867 */
1868int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001869xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1870 unsigned char *array ATTRIBUTE_UNUSED,
1871 int offset ATTRIBUTE_UNUSED,
1872 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001873 if ((reader == NULL) || (reader->ctxt == NULL))
1874 return(-1);
1875 if (reader->ctxt->wellFormed != 1)
1876 return(-1);
1877
1878 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1879 return(0);
1880 TODO
1881 return(0);
1882}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001883#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001884
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001885/************************************************************************
1886 * *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001887 * Operating on a preparsed tree *
1888 * *
1889 ************************************************************************/
1890static int
1891xmlTextReaderNextTree(xmlTextReaderPtr reader)
1892{
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001893 if (reader == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001894 return(-1);
1895
1896 if (reader->state == XML_TEXTREADER_END)
1897 return(0);
1898
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001899 if (reader->node == NULL) {
1900 if (reader->doc->children == NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001901 reader->state = XML_TEXTREADER_END;
1902 return(0);
1903 }
1904
1905 reader->node = reader->doc->children;
1906 reader->state = XML_TEXTREADER_START;
1907 return(1);
1908 }
1909
1910 if (reader->state != XML_TEXTREADER_BACKTRACK) {
Daniel Veillardbfa5cf12008-08-27 15:33:28 +00001911 /* Here removed traversal to child, because we want to skip the subtree,
Daniel Veillardaa6de472008-08-25 14:53:31 +00001912 replace with traversal to sibling to skip subtree */
1913 if (reader->node->next != 0) {
Daniel Veillardbfa5cf12008-08-27 15:33:28 +00001914 /* Move to sibling if present,skipping sub-tree */
1915 reader->node = reader->node->next;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001916 reader->state = XML_TEXTREADER_START;
1917 return(1);
1918 }
Daniel Veillardbfa5cf12008-08-27 15:33:28 +00001919
1920 /* if reader->node->next is NULL mean no subtree for current node,
Daniel Veillardaa6de472008-08-25 14:53:31 +00001921 so need to move to sibling of parent node if present */
Elliott Hughes7fbecab2019-01-10 16:42:03 -08001922 reader->state = XML_TEXTREADER_BACKTRACK;
1923 /* This will move to parent if present */
1924 xmlTextReaderRead(reader);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001925 }
1926
1927 if (reader->node->next != 0) {
1928 reader->node = reader->node->next;
1929 reader->state = XML_TEXTREADER_START;
1930 return(1);
1931 }
1932
1933 if (reader->node->parent != 0) {
1934 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1935 reader->state = XML_TEXTREADER_END;
1936 return(0);
1937 }
1938
1939 reader->node = reader->node->parent;
1940 reader->depth--;
1941 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillardbfa5cf12008-08-27 15:33:28 +00001942 /* Repeat process to move to sibling of parent node if present */
1943 xmlTextReaderNextTree(reader);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001944 }
1945
1946 reader->state = XML_TEXTREADER_END;
1947
1948 return(1);
1949}
1950
1951/**
1952 * xmlTextReaderReadTree:
1953 * @reader: the xmlTextReaderPtr used
1954 *
1955 * Moves the position of the current instance to the next node in
1956 * the stream, exposing its properties.
1957 *
1958 * Returns 1 if the node was read successfully, 0 if there is no more
1959 * nodes to read, or -1 in case of error
1960 */
1961static int
1962xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1963 if (reader->state == XML_TEXTREADER_END)
1964 return(0);
1965
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001966next_node:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001967 if (reader->node == NULL) {
1968 if (reader->doc->children == NULL) {
1969 reader->state = XML_TEXTREADER_END;
1970 return(0);
1971 }
1972
1973 reader->node = reader->doc->children;
1974 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001975 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001976 }
1977
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001978 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1979 (reader->node->type != XML_DTD_NODE) &&
1980 (reader->node->type != XML_XINCLUDE_START) &&
1981 (reader->node->type != XML_ENTITY_REF_NODE)) {
1982 if (reader->node->children != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001983 reader->node = reader->node->children;
1984 reader->depth++;
1985 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001986 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001987 }
1988
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001989 if (reader->node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001990 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001991 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001992 }
1993 }
1994
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001995 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001996 reader->node = reader->node->next;
1997 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001998 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001999 }
2000
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002001 if (reader->node->parent != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002002 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
2003 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
2004 reader->state = XML_TEXTREADER_END;
2005 return(0);
2006 }
2007
2008 reader->node = reader->node->parent;
2009 reader->depth--;
2010 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002011 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002012 }
2013
2014 reader->state = XML_TEXTREADER_END;
2015
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002016found_node:
2017 if ((reader->node->type == XML_XINCLUDE_START) ||
2018 (reader->node->type == XML_XINCLUDE_END))
2019 goto next_node;
2020
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002021 return(1);
2022}
2023
2024/**
William M. Brackb1d53162003-11-18 06:54:40 +00002025 * xmlTextReaderNextSibling:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002026 * @reader: the xmlTextReaderPtr used
2027 *
2028 * Skip to the node following the current one in document order while
2029 * avoiding the subtree if any.
2030 * Currently implemented only for Readers built on a document
2031 *
2032 * Returns 1 if the node was read successfully, 0 if there is no more
2033 * nodes to read, or -1 in case of error
2034 */
2035int
2036xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
2037 if (reader == NULL)
2038 return(-1);
2039 if (reader->doc == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002040 /* TODO */
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002041 return(-1);
2042 }
2043
2044 if (reader->state == XML_TEXTREADER_END)
2045 return(0);
2046
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002047 if (reader->node == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002048 return(xmlTextReaderNextTree(reader));
2049
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002050 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002051 reader->node = reader->node->next;
2052 reader->state = XML_TEXTREADER_START;
2053 return(1);
2054 }
2055
2056 return(0);
2057}
2058
2059/************************************************************************
2060 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002061 * Constructor and destructors *
2062 * *
2063 ************************************************************************/
2064/**
2065 * xmlNewTextReader:
2066 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00002067 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002068 *
2069 * Create an xmlTextReader structure fed with @input
2070 *
2071 * Returns the new xmlTextReaderPtr or NULL in case of error
2072 */
2073xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00002074xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002075 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002076
2077 if (input == NULL)
2078 return(NULL);
2079 ret = xmlMalloc(sizeof(xmlTextReader));
2080 if (ret == NULL) {
2081 xmlGenericError(xmlGenericErrorContext,
2082 "xmlNewTextReader : malloc failed\n");
2083 return(NULL);
2084 }
2085 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002086 ret->doc = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002087 ret->entTab = NULL;
2088 ret->entMax = 0;
2089 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002090 ret->input = input;
Daniel Veillard8aebce32012-07-16 14:42:31 +08002091 ret->buffer = xmlBufCreateSize(100);
William M. Bracka3215c72004-07-31 16:24:01 +00002092 if (ret->buffer == NULL) {
2093 xmlFree(ret);
2094 xmlGenericError(xmlGenericErrorContext,
2095 "xmlNewTextReader : malloc failed\n");
2096 return(NULL);
2097 }
Daniel Veillard213f1fe2015-04-14 17:41:48 +08002098 /* no operation on a reader should require a huge buffer */
2099 xmlBufSetAllocationScheme(ret->buffer,
2100 XML_BUFFER_ALLOC_BOUNDED);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002101 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
2102 if (ret->sax == NULL) {
Daniel Veillard8aebce32012-07-16 14:42:31 +08002103 xmlBufFree(ret->buffer);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002104 xmlFree(ret);
2105 xmlGenericError(xmlGenericErrorContext,
2106 "xmlNewTextReader : malloc failed\n");
2107 return(NULL);
2108 }
Daniel Veillard81273902003-09-30 00:43:48 +00002109 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002110 ret->startElement = ret->sax->startElement;
2111 ret->sax->startElement = xmlTextReaderStartElement;
2112 ret->endElement = ret->sax->endElement;
2113 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00002114#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002115 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00002116#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00002117 ret->startElementNs = ret->sax->startElementNs;
2118 ret->sax->startElementNs = xmlTextReaderStartElementNs;
2119 ret->endElementNs = ret->sax->endElementNs;
2120 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00002121#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002122 } else {
2123 ret->startElementNs = NULL;
2124 ret->endElementNs = NULL;
2125 }
Daniel Veillard81273902003-09-30 00:43:48 +00002126#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00002127 ret->characters = ret->sax->characters;
2128 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002129 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002130 ret->cdataBlock = ret->sax->cdataBlock;
2131 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002132
Daniel Veillard67df8092002-12-16 22:04:11 +00002133 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002134 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002135 ret->curnode = NULL;
Daniel Veillard8aebce32012-07-16 14:42:31 +08002136 if (xmlBufUse(ret->input->buffer) < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00002137 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00002138 }
Daniel Veillard8aebce32012-07-16 14:42:31 +08002139 if (xmlBufUse(ret->input->buffer) >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002140 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillard8aebce32012-07-16 14:42:31 +08002141 (const char *) xmlBufContent(ret->input->buffer),
2142 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002143 ret->base = 0;
2144 ret->cur = 4;
2145 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00002146 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002147 ret->base = 0;
2148 ret->cur = 0;
2149 }
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002150
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002151 if (ret->ctxt == NULL) {
2152 xmlGenericError(xmlGenericErrorContext,
2153 "xmlNewTextReader : malloc failed\n");
Daniel Veillard8aebce32012-07-16 14:42:31 +08002154 xmlBufFree(ret->buffer);
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002155 xmlFree(ret->sax);
2156 xmlFree(ret);
2157 return(NULL);
2158 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00002159 ret->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002160 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002161 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00002162 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002163 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002164 /*
Jan Pokornýbb654fe2016-04-13 16:56:07 +02002165 * use the parser dictionary to allocate all elements and attributes names
Daniel Veillard40412cd2003-09-03 13:28:32 +00002166 */
2167 ret->ctxt->docdict = 1;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002168 ret->dict = ret->ctxt->dict;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002169#ifdef LIBXML_XINCLUDE_ENABLED
2170 ret->xinclude = 0;
2171#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002172#ifdef LIBXML_PATTERN_ENABLED
2173 ret->patternMax = 0;
2174 ret->patternTab = NULL;
2175#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002176 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002177}
2178
2179/**
2180 * xmlNewTextReaderFilename:
2181 * @URI: the URI of the resource to process
2182 *
2183 * Create an xmlTextReader structure fed with the resource at @URI
2184 *
2185 * Returns the new xmlTextReaderPtr or NULL in case of error
2186 */
2187xmlTextReaderPtr
2188xmlNewTextReaderFilename(const char *URI) {
2189 xmlParserInputBufferPtr input;
2190 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002191 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002192
2193 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
2194 if (input == NULL)
2195 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00002196 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002197 if (ret == NULL) {
2198 xmlFreeParserInputBuffer(input);
2199 return(NULL);
2200 }
2201 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002202 if (ret->ctxt->directory == NULL)
2203 directory = xmlParserGetDirectory(URI);
2204 if ((ret->ctxt->directory == NULL) && (directory != NULL))
2205 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
2206 if (directory != NULL)
2207 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002208 return(ret);
2209}
2210
2211/**
2212 * xmlFreeTextReader:
2213 * @reader: the xmlTextReaderPtr
2214 *
2215 * Deallocate all the resources associated to the reader
2216 */
2217void
2218xmlFreeTextReader(xmlTextReaderPtr reader) {
2219 if (reader == NULL)
2220 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002221#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00002222 if (reader->rngSchemas != NULL) {
2223 xmlRelaxNGFree(reader->rngSchemas);
2224 reader->rngSchemas = NULL;
2225 }
2226 if (reader->rngValidCtxt != NULL) {
Noam Postavsky15794992012-03-19 16:08:16 +08002227 if (! reader->rngPreserveCtxt)
2228 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
Daniel Veillardf4e55762003-04-15 23:32:22 +00002229 reader->rngValidCtxt = NULL;
2230 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00002231 if (reader->xsdPlug != NULL) {
2232 xmlSchemaSAXUnplug(reader->xsdPlug);
2233 reader->xsdPlug = NULL;
2234 }
2235 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00002236 if (! reader->xsdPreserveCtxt)
2237 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00002238 reader->xsdValidCtxt = NULL;
2239 }
2240 if (reader->xsdSchemas != NULL) {
2241 xmlSchemaFree(reader->xsdSchemas);
2242 reader->xsdSchemas = NULL;
2243 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002244#endif
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002245#ifdef LIBXML_XINCLUDE_ENABLED
2246 if (reader->xincctxt != NULL)
2247 xmlXIncludeFreeContext(reader->xincctxt);
2248#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002249#ifdef LIBXML_PATTERN_ENABLED
2250 if (reader->patternTab != NULL) {
2251 int i;
2252 for (i = 0;i < reader->patternNr;i++) {
2253 if (reader->patternTab[i] != NULL)
2254 xmlFreePattern(reader->patternTab[i]);
2255 }
2256 xmlFree(reader->patternTab);
2257 }
2258#endif
Daniel Veillardf4653dc2009-08-21 18:40:50 +02002259 if (reader->faketext != NULL) {
2260 xmlFreeNode(reader->faketext);
2261 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002262 if (reader->ctxt != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002263 if (reader->dict == reader->ctxt->dict)
2264 reader->dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002265 if (reader->ctxt->myDoc != NULL) {
2266 if (reader->preserve == 0)
2267 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2268 reader->ctxt->myDoc = NULL;
2269 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002270 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2271 (reader->ctxt->vctxt.vstateMax > 0)){
2272 xmlFree(reader->ctxt->vctxt.vstateTab);
Daniel Veillard75e389d2005-07-29 22:02:24 +00002273 reader->ctxt->vctxt.vstateTab = NULL;
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002274 reader->ctxt->vctxt.vstateMax = 0;
2275 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002276 if (reader->allocs & XML_TEXTREADER_CTXT)
2277 xmlFreeParserCtxt(reader->ctxt);
2278 }
2279 if (reader->sax != NULL)
2280 xmlFree(reader->sax);
2281 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
2282 xmlFreeParserInputBuffer(reader->input);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002283 if (reader->buffer != NULL)
Daniel Veillard8aebce32012-07-16 14:42:31 +08002284 xmlBufFree(reader->buffer);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002285 if (reader->entTab != NULL)
2286 xmlFree(reader->entTab);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002287 if (reader->dict != NULL)
2288 xmlDictFree(reader->dict);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002289 xmlFree(reader);
2290}
2291
2292/************************************************************************
2293 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002294 * Methods for XmlTextReader *
2295 * *
2296 ************************************************************************/
2297/**
2298 * xmlTextReaderClose:
2299 * @reader: the xmlTextReaderPtr used
2300 *
2301 * This method releases any resources allocated by the current instance
2302 * changes the state to Closed and close any underlying input.
2303 *
2304 * Returns 0 or -1 in case of error
2305 */
2306int
2307xmlTextReaderClose(xmlTextReaderPtr reader) {
2308 if (reader == NULL)
2309 return(-1);
2310 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002311 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002312 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2313 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002314 xmlStopParser(reader->ctxt);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002315 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002316 if (reader->preserve == 0)
2317 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002318 reader->ctxt->myDoc = NULL;
2319 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002320 }
2321 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2322 xmlFreeParserInputBuffer(reader->input);
2323 reader->allocs -= XML_TEXTREADER_INPUT;
2324 }
2325 return(0);
2326}
2327
2328/**
2329 * xmlTextReaderGetAttributeNo:
2330 * @reader: the xmlTextReaderPtr used
2331 * @no: the zero-based index of the attribute relative to the containing element
2332 *
2333 * Provides the value of the attribute with the specified index relative
2334 * to the containing element.
2335 *
2336 * Returns a string containing the value of the specified attribute, or NULL
2337 * in case of error. The string must be deallocated by the caller.
2338 */
2339xmlChar *
2340xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2341 xmlChar *ret;
2342 int i;
2343 xmlAttrPtr cur;
2344 xmlNsPtr ns;
2345
2346 if (reader == NULL)
2347 return(NULL);
2348 if (reader->node == NULL)
2349 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002350 if (reader->curnode != NULL)
2351 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002352 /* TODO: handle the xmlDecl */
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002353 if (reader->node->type != XML_ELEMENT_NODE)
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002354 return(NULL);
2355
2356 ns = reader->node->nsDef;
2357 for (i = 0;(i < no) && (ns != NULL);i++) {
2358 ns = ns->next;
2359 }
2360 if (ns != NULL)
2361 return(xmlStrdup(ns->href));
2362
2363 cur = reader->node->properties;
2364 if (cur == NULL)
2365 return(NULL);
2366 for (;i < no;i++) {
2367 cur = cur->next;
2368 if (cur == NULL)
2369 return(NULL);
2370 }
2371 /* TODO walk the DTD if present */
2372
2373 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2374 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2375 return(ret);
2376}
2377
2378/**
2379 * xmlTextReaderGetAttribute:
2380 * @reader: the xmlTextReaderPtr used
2381 * @name: the qualified name of the attribute.
2382 *
2383 * Provides the value of the attribute with the specified qualified name.
2384 *
2385 * Returns a string containing the value of the specified attribute, or NULL
2386 * in case of error. The string must be deallocated by the caller.
2387 */
2388xmlChar *
2389xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2390 xmlChar *prefix = NULL;
2391 xmlChar *localname;
2392 xmlNsPtr ns;
2393 xmlChar *ret = NULL;
2394
2395 if ((reader == NULL) || (name == NULL))
2396 return(NULL);
2397 if (reader->node == NULL)
2398 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002399 if (reader->curnode != NULL)
2400 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002401
2402 /* TODO: handle the xmlDecl */
2403 if (reader->node->type != XML_ELEMENT_NODE)
2404 return(NULL);
2405
2406 localname = xmlSplitQName2(name, &prefix);
Daniel Veillard3c40e612005-08-17 07:07:44 +00002407 if (localname == NULL) {
2408 /*
2409 * Namespace default decl
2410 */
2411 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2412 ns = reader->node->nsDef;
2413 while (ns != NULL) {
2414 if (ns->prefix == NULL) {
2415 return(xmlStrdup(ns->href));
2416 }
2417 ns = ns->next;
2418 }
2419 return NULL;
2420 }
2421 return(xmlGetNoNsProp(reader->node, name));
2422 }
2423
2424 /*
2425 * Namespace default decl
2426 */
2427 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2428 ns = reader->node->nsDef;
2429 while (ns != NULL) {
2430 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2431 ret = xmlStrdup(ns->href);
2432 break;
2433 }
2434 ns = ns->next;
2435 }
2436 } else {
2437 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2438 if (ns != NULL)
2439 ret = xmlGetNsProp(reader->node, localname, ns->href);
2440 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002441
Daniel Veillardc4ff8322005-08-08 07:45:23 +00002442 xmlFree(localname);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002443 if (prefix != NULL)
2444 xmlFree(prefix);
2445 return(ret);
2446}
2447
2448
2449/**
2450 * xmlTextReaderGetAttributeNs:
2451 * @reader: the xmlTextReaderPtr used
2452 * @localName: the local name of the attribute.
2453 * @namespaceURI: the namespace URI of the attribute.
2454 *
2455 * Provides the value of the specified attribute
2456 *
2457 * Returns a string containing the value of the specified attribute, or NULL
2458 * in case of error. The string must be deallocated by the caller.
2459 */
2460xmlChar *
2461xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2462 const xmlChar *namespaceURI) {
Daniel Veillard45b97e72005-08-20 21:14:28 +00002463 xmlChar *prefix = NULL;
2464 xmlNsPtr ns;
2465
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002466 if ((reader == NULL) || (localName == NULL))
2467 return(NULL);
2468 if (reader->node == NULL)
2469 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002470 if (reader->curnode != NULL)
2471 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002472
2473 /* TODO: handle the xmlDecl */
2474 if (reader->node->type != XML_ELEMENT_NODE)
2475 return(NULL);
2476
Daniel Veillard45b97e72005-08-20 21:14:28 +00002477 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2478 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2479 prefix = BAD_CAST localName;
2480 }
2481 ns = reader->node->nsDef;
2482 while (ns != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002483 if ((prefix == NULL && ns->prefix == NULL) ||
Daniel Veillard45b97e72005-08-20 21:14:28 +00002484 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2485 return xmlStrdup(ns->href);
2486 }
2487 ns = ns->next;
2488 }
2489 return NULL;
2490 }
2491
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002492 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2493}
2494
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002495/**
2496 * xmlTextReaderGetRemainder:
2497 * @reader: the xmlTextReaderPtr used
2498 *
2499 * Method to get the remainder of the buffered XML. this method stops the
2500 * parser, set its state to End Of File and return the input stream with
2501 * what is left that the parser did not use.
2502 *
Daniel Veillardee1d6922004-04-18 14:58:57 +00002503 * The implementation is not good, the parser certainly procgressed past
2504 * what's left in reader->input, and there is an allocation problem. Best
2505 * would be to rewrite it differently.
2506 *
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002507 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2508 * in case of error.
2509 */
2510xmlParserInputBufferPtr
2511xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2512 xmlParserInputBufferPtr ret = NULL;
2513
2514 if (reader == NULL)
2515 return(NULL);
2516 if (reader->node == NULL)
2517 return(NULL);
2518
2519 reader->node = NULL;
2520 reader->curnode = NULL;
2521 reader->mode = XML_TEXTREADER_MODE_EOF;
2522 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002523 xmlStopParser(reader->ctxt);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002524 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002525 if (reader->preserve == 0)
2526 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002527 reader->ctxt->myDoc = NULL;
2528 }
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002529 }
2530 if (reader->allocs & XML_TEXTREADER_INPUT) {
2531 ret = reader->input;
Daniel Veillardee1d6922004-04-18 14:58:57 +00002532 reader->input = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002533 reader->allocs -= XML_TEXTREADER_INPUT;
2534 } else {
2535 /*
2536 * Hum, one may need to duplicate the data structure because
2537 * without reference counting the input may be freed twice:
2538 * - by the layer which allocated it.
2539 * - by the layer to which would have been returned to.
2540 */
2541 TODO
2542 return(NULL);
2543 }
2544 return(ret);
2545}
2546
2547/**
2548 * xmlTextReaderLookupNamespace:
2549 * @reader: the xmlTextReaderPtr used
2550 * @prefix: the prefix whose namespace URI is to be resolved. To return
2551 * the default namespace, specify NULL
2552 *
2553 * Resolves a namespace prefix in the scope of the current element.
2554 *
2555 * Returns a string containing the namespace URI to which the prefix maps
2556 * or NULL in case of error. The string must be deallocated by the caller.
2557 */
2558xmlChar *
2559xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2560 xmlNsPtr ns;
2561
2562 if (reader == NULL)
2563 return(NULL);
2564 if (reader->node == NULL)
2565 return(NULL);
2566
2567 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2568 if (ns == NULL)
2569 return(NULL);
2570 return(xmlStrdup(ns->href));
2571}
2572
2573/**
2574 * xmlTextReaderMoveToAttributeNo:
2575 * @reader: the xmlTextReaderPtr used
2576 * @no: the zero-based index of the attribute relative to the containing
2577 * element.
2578 *
2579 * Moves the position of the current instance to the attribute with
2580 * the specified index relative to the containing element.
2581 *
2582 * Returns 1 in case of success, -1 in case of error, 0 if not found
2583 */
2584int
2585xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2586 int i;
2587 xmlAttrPtr cur;
2588 xmlNsPtr ns;
2589
2590 if (reader == NULL)
2591 return(-1);
2592 if (reader->node == NULL)
2593 return(-1);
2594 /* TODO: handle the xmlDecl */
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002595 if (reader->node->type != XML_ELEMENT_NODE)
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002596 return(-1);
2597
2598 reader->curnode = NULL;
2599
2600 ns = reader->node->nsDef;
2601 for (i = 0;(i < no) && (ns != NULL);i++) {
2602 ns = ns->next;
2603 }
2604 if (ns != NULL) {
2605 reader->curnode = (xmlNodePtr) ns;
2606 return(1);
2607 }
2608
2609 cur = reader->node->properties;
2610 if (cur == NULL)
2611 return(0);
2612 for (;i < no;i++) {
2613 cur = cur->next;
2614 if (cur == NULL)
2615 return(0);
2616 }
2617 /* TODO walk the DTD if present */
2618
2619 reader->curnode = (xmlNodePtr) cur;
2620 return(1);
2621}
2622
2623/**
2624 * xmlTextReaderMoveToAttribute:
2625 * @reader: the xmlTextReaderPtr used
2626 * @name: the qualified name of the attribute.
2627 *
2628 * Moves the position of the current instance to the attribute with
2629 * the specified qualified name.
2630 *
2631 * Returns 1 in case of success, -1 in case of error, 0 if not found
2632 */
2633int
2634xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2635 xmlChar *prefix = NULL;
2636 xmlChar *localname;
2637 xmlNsPtr ns;
2638 xmlAttrPtr prop;
2639
2640 if ((reader == NULL) || (name == NULL))
2641 return(-1);
2642 if (reader->node == NULL)
2643 return(-1);
2644
2645 /* TODO: handle the xmlDecl */
2646 if (reader->node->type != XML_ELEMENT_NODE)
2647 return(0);
2648
2649 localname = xmlSplitQName2(name, &prefix);
2650 if (localname == NULL) {
2651 /*
2652 * Namespace default decl
2653 */
2654 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2655 ns = reader->node->nsDef;
2656 while (ns != NULL) {
2657 if (ns->prefix == NULL) {
2658 reader->curnode = (xmlNodePtr) ns;
2659 return(1);
2660 }
2661 ns = ns->next;
2662 }
2663 return(0);
2664 }
2665
2666 prop = reader->node->properties;
2667 while (prop != NULL) {
2668 /*
2669 * One need to have
2670 * - same attribute names
2671 * - and the attribute carrying that namespace
2672 */
2673 if ((xmlStrEqual(prop->name, name)) &&
2674 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2675 reader->curnode = (xmlNodePtr) prop;
2676 return(1);
2677 }
2678 prop = prop->next;
2679 }
2680 return(0);
2681 }
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002682
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002683 /*
2684 * Namespace default decl
2685 */
2686 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2687 ns = reader->node->nsDef;
2688 while (ns != NULL) {
2689 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2690 reader->curnode = (xmlNodePtr) ns;
2691 goto found;
2692 }
2693 ns = ns->next;
2694 }
2695 goto not_found;
2696 }
2697 prop = reader->node->properties;
2698 while (prop != NULL) {
2699 /*
2700 * One need to have
2701 * - same attribute names
2702 * - and the attribute carrying that namespace
2703 */
2704 if ((xmlStrEqual(prop->name, localname)) &&
2705 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2706 reader->curnode = (xmlNodePtr) prop;
2707 goto found;
2708 }
2709 prop = prop->next;
2710 }
2711not_found:
2712 if (localname != NULL)
2713 xmlFree(localname);
2714 if (prefix != NULL)
2715 xmlFree(prefix);
2716 return(0);
2717
2718found:
2719 if (localname != NULL)
2720 xmlFree(localname);
2721 if (prefix != NULL)
2722 xmlFree(prefix);
2723 return(1);
2724}
2725
2726/**
2727 * xmlTextReaderMoveToAttributeNs:
2728 * @reader: the xmlTextReaderPtr used
2729 * @localName: the local name of the attribute.
2730 * @namespaceURI: the namespace URI of the attribute.
2731 *
2732 * Moves the position of the current instance to the attribute with the
2733 * specified local name and namespace URI.
2734 *
2735 * Returns 1 in case of success, -1 in case of error, 0 if not found
2736 */
2737int
2738xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2739 const xmlChar *localName, const xmlChar *namespaceURI) {
2740 xmlAttrPtr prop;
2741 xmlNodePtr node;
Daniel Veillard45b97e72005-08-20 21:14:28 +00002742 xmlNsPtr ns;
2743 xmlChar *prefix = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002744
2745 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2746 return(-1);
2747 if (reader->node == NULL)
2748 return(-1);
2749 if (reader->node->type != XML_ELEMENT_NODE)
2750 return(0);
2751 node = reader->node;
2752
Daniel Veillard45b97e72005-08-20 21:14:28 +00002753 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2754 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2755 prefix = BAD_CAST localName;
2756 }
2757 ns = reader->node->nsDef;
2758 while (ns != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002759 if ((prefix == NULL && ns->prefix == NULL) ||
Daniel Veillard45b97e72005-08-20 21:14:28 +00002760 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2761 reader->curnode = (xmlNodePtr) ns;
2762 return(1);
2763 }
2764 ns = ns->next;
2765 }
2766 return(0);
2767 }
2768
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002769 prop = node->properties;
2770 while (prop != NULL) {
2771 /*
2772 * One need to have
2773 * - same attribute names
2774 * - and the attribute carrying that namespace
2775 */
2776 if (xmlStrEqual(prop->name, localName) &&
2777 ((prop->ns != NULL) &&
2778 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2779 reader->curnode = (xmlNodePtr) prop;
2780 return(1);
2781 }
2782 prop = prop->next;
2783 }
2784 return(0);
2785}
2786
2787/**
2788 * xmlTextReaderMoveToFirstAttribute:
2789 * @reader: the xmlTextReaderPtr used
2790 *
2791 * Moves the position of the current instance to the first attribute
2792 * associated with the current node.
2793 *
2794 * Returns 1 in case of success, -1 in case of error, 0 if not found
2795 */
2796int
2797xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2798 if (reader == NULL)
2799 return(-1);
2800 if (reader->node == NULL)
2801 return(-1);
2802 if (reader->node->type != XML_ELEMENT_NODE)
2803 return(0);
2804
2805 if (reader->node->nsDef != NULL) {
2806 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2807 return(1);
2808 }
2809 if (reader->node->properties != NULL) {
2810 reader->curnode = (xmlNodePtr) reader->node->properties;
2811 return(1);
2812 }
2813 return(0);
2814}
2815
2816/**
2817 * xmlTextReaderMoveToNextAttribute:
2818 * @reader: the xmlTextReaderPtr used
2819 *
2820 * Moves the position of the current instance to the next attribute
2821 * associated with the current node.
2822 *
2823 * Returns 1 in case of success, -1 in case of error, 0 if not found
2824 */
2825int
2826xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2827 if (reader == NULL)
2828 return(-1);
2829 if (reader->node == NULL)
2830 return(-1);
2831 if (reader->node->type != XML_ELEMENT_NODE)
2832 return(0);
2833 if (reader->curnode == NULL)
2834 return(xmlTextReaderMoveToFirstAttribute(reader));
2835
2836 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2837 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2838 if (ns->next != NULL) {
2839 reader->curnode = (xmlNodePtr) ns->next;
2840 return(1);
2841 }
2842 if (reader->node->properties != NULL) {
2843 reader->curnode = (xmlNodePtr) reader->node->properties;
2844 return(1);
2845 }
2846 return(0);
2847 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2848 (reader->curnode->next != NULL)) {
2849 reader->curnode = reader->curnode->next;
2850 return(1);
2851 }
2852 return(0);
2853}
2854
2855/**
2856 * xmlTextReaderMoveToElement:
2857 * @reader: the xmlTextReaderPtr used
2858 *
2859 * Moves the position of the current instance to the node that
2860 * contains the current Attribute node.
2861 *
2862 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2863 */
2864int
2865xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2866 if (reader == NULL)
2867 return(-1);
2868 if (reader->node == NULL)
2869 return(-1);
2870 if (reader->node->type != XML_ELEMENT_NODE)
2871 return(0);
2872 if (reader->curnode != NULL) {
2873 reader->curnode = NULL;
2874 return(1);
2875 }
2876 return(0);
2877}
2878
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002879/**
2880 * xmlTextReaderReadAttributeValue:
2881 * @reader: the xmlTextReaderPtr used
2882 *
2883 * Parses an attribute value into one or more Text and EntityReference nodes.
2884 *
2885 * Returns 1 in case of success, 0 if the reader was not positionned on an
2886 * ttribute node or all the attribute values have been read, or -1
2887 * in case of error.
2888 */
2889int
2890xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2891 if (reader == NULL)
2892 return(-1);
2893 if (reader->node == NULL)
2894 return(-1);
2895 if (reader->curnode == NULL)
2896 return(0);
2897 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2898 if (reader->curnode->children == NULL)
2899 return(0);
2900 reader->curnode = reader->curnode->children;
2901 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2902 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2903
2904 if (reader->faketext == NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002905 reader->faketext = xmlNewDocText(reader->node->doc,
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002906 ns->href);
2907 } else {
Daniel Veillard8874b942005-08-25 13:19:21 +00002908 if ((reader->faketext->content != NULL) &&
2909 (reader->faketext->content !=
2910 (xmlChar *) &(reader->faketext->properties)))
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002911 xmlFree(reader->faketext->content);
2912 reader->faketext->content = xmlStrdup(ns->href);
2913 }
2914 reader->curnode = reader->faketext;
2915 } else {
2916 if (reader->curnode->next == NULL)
2917 return(0);
2918 reader->curnode = reader->curnode->next;
2919 }
2920 return(1);
2921}
2922
Daniel Veillarde2811272004-10-19 09:04:23 +00002923/**
2924 * xmlTextReaderConstEncoding:
2925 * @reader: the xmlTextReaderPtr used
2926 *
2927 * Determine the encoding of the document being read.
2928 *
2929 * Returns a string containing the encoding of the document or NULL in
2930 * case of error. The string is deallocated with the reader.
2931 */
2932const xmlChar *
2933xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
2934 xmlDocPtr doc = NULL;
2935 if (reader == NULL)
2936 return(NULL);
2937 if (reader->doc != NULL)
2938 doc = reader->doc;
2939 else if (reader->ctxt != NULL)
2940 doc = reader->ctxt->myDoc;
2941 if (doc == NULL)
2942 return(NULL);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002943
Daniel Veillarde2811272004-10-19 09:04:23 +00002944 if (doc->encoding == NULL)
2945 return(NULL);
2946 else
2947 return(CONSTSTR(doc->encoding));
2948}
2949
2950
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002951/************************************************************************
2952 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002953 * Acces API to the current node *
2954 * *
2955 ************************************************************************/
2956/**
2957 * xmlTextReaderAttributeCount:
2958 * @reader: the xmlTextReaderPtr used
2959 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002960 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002961 *
2962 * Returns 0 i no attributes, -1 in case of error or the attribute count
2963 */
2964int
2965xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2966 int ret;
2967 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002968 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002969 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002970
2971 if (reader == NULL)
2972 return(-1);
2973 if (reader->node == NULL)
2974 return(0);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002975
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002976 if (reader->curnode != NULL)
2977 node = reader->curnode;
2978 else
2979 node = reader->node;
2980
2981 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002982 return(0);
2983 if ((reader->state == XML_TEXTREADER_END) ||
2984 (reader->state == XML_TEXTREADER_BACKTRACK))
2985 return(0);
2986 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002987 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002988 while (attr != NULL) {
2989 ret++;
2990 attr = attr->next;
2991 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002992 ns = node->nsDef;
2993 while (ns != NULL) {
2994 ret++;
2995 ns = ns->next;
2996 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002997 return(ret);
2998}
2999
3000/**
3001 * xmlTextReaderNodeType:
3002 * @reader: the xmlTextReaderPtr used
3003 *
3004 * Get the node type of the current node
3005 * Reference:
Daniel Veillard354cf5c2008-04-07 12:46:48 +00003006 * http://www.gnu.org/software/dotgnu/pnetlib-doc/System/Xml/XmlNodeType.html
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003007 *
Elliott Hughes7fbecab2019-01-10 16:42:03 -08003008 * Returns the xmlReaderTypes of the current node or -1 in case of error
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003009 */
3010int
3011xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003012 xmlNodePtr node;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003013
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003014 if (reader == NULL)
3015 return(-1);
3016 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00003017 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003018 if (reader->curnode != NULL)
3019 node = reader->curnode;
3020 else
3021 node = reader->node;
3022 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003023 case XML_ELEMENT_NODE:
3024 if ((reader->state == XML_TEXTREADER_END) ||
3025 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00003026 return(XML_READER_TYPE_END_ELEMENT);
3027 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00003028 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003029 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003030 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003031 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003032 if (xmlIsBlankNode(reader->node)) {
3033 if (xmlNodeGetSpacePreserve(reader->node))
3034 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
3035 else
3036 return(XML_READER_TYPE_WHITESPACE);
3037 } else {
3038 return(XML_READER_TYPE_TEXT);
3039 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003040 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003041 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003042 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003043 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003044 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003045 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003046 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003047 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003048 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003049 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003050 case XML_DOCUMENT_NODE:
3051 case XML_HTML_DOCUMENT_NODE:
3052#ifdef LIBXML_DOCB_ENABLED
3053 case XML_DOCB_DOCUMENT_NODE:
3054#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00003055 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003056 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003057 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003058 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003059 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003060 case XML_DOCUMENT_TYPE_NODE:
3061 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003062 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003063
3064 case XML_ELEMENT_DECL:
3065 case XML_ATTRIBUTE_DECL:
3066 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003067 case XML_XINCLUDE_START:
3068 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003069 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003070 }
3071 return(-1);
3072}
3073
3074/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00003075 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003076 * @reader: the xmlTextReaderPtr used
3077 *
3078 * Check if the current node is empty
3079 *
3080 * Returns 1 if empty, 0 if not and -1 in case of error
3081 */
3082int
3083xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
3084 if ((reader == NULL) || (reader->node == NULL))
3085 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00003086 if (reader->node->type != XML_ELEMENT_NODE)
3087 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00003088 if (reader->curnode != NULL)
3089 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003090 if (reader->node->children != NULL)
3091 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00003092 if (reader->state == XML_TEXTREADER_END)
3093 return(0);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00003094 if (reader->doc != NULL)
3095 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00003096#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard7899c5c2003-11-03 12:31:38 +00003097 if (reader->in_xinclude > 0)
3098 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00003099#endif
Daniel Veillarde8039df2003-10-27 11:25:13 +00003100 return((reader->node->extra & NODE_IS_EMPTY) != 0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003101}
3102
3103/**
3104 * xmlTextReaderLocalName:
3105 * @reader: the xmlTextReaderPtr used
3106 *
3107 * The local name of the node.
3108 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003109 * Returns the local name or NULL if not available,
3110 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003111 */
3112xmlChar *
3113xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003114 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003115 if ((reader == NULL) || (reader->node == NULL))
3116 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003117 if (reader->curnode != NULL)
3118 node = reader->curnode;
3119 else
3120 node = reader->node;
3121 if (node->type == XML_NAMESPACE_DECL) {
3122 xmlNsPtr ns = (xmlNsPtr) node;
3123 if (ns->prefix == NULL)
3124 return(xmlStrdup(BAD_CAST "xmlns"));
3125 else
3126 return(xmlStrdup(ns->prefix));
3127 }
3128 if ((node->type != XML_ELEMENT_NODE) &&
3129 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003130 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003131 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003132}
3133
3134/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003135 * xmlTextReaderConstLocalName:
3136 * @reader: the xmlTextReaderPtr used
3137 *
3138 * The local name of the node.
3139 *
3140 * Returns the local name or NULL if not available, the
3141 * string will be deallocated with the reader.
3142 */
3143const xmlChar *
3144xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
3145 xmlNodePtr node;
3146 if ((reader == NULL) || (reader->node == NULL))
3147 return(NULL);
3148 if (reader->curnode != NULL)
3149 node = reader->curnode;
3150 else
3151 node = reader->node;
3152 if (node->type == XML_NAMESPACE_DECL) {
3153 xmlNsPtr ns = (xmlNsPtr) node;
3154 if (ns->prefix == NULL)
3155 return(CONSTSTR(BAD_CAST "xmlns"));
3156 else
3157 return(ns->prefix);
3158 }
3159 if ((node->type != XML_ELEMENT_NODE) &&
3160 (node->type != XML_ATTRIBUTE_NODE))
3161 return(xmlTextReaderConstName(reader));
3162 return(node->name);
3163}
3164
3165/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003166 * xmlTextReaderName:
3167 * @reader: the xmlTextReaderPtr used
3168 *
3169 * The qualified name of the node, equal to Prefix :LocalName.
3170 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003171 * Returns the local name or NULL if not available,
3172 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003173 */
3174xmlChar *
3175xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003176 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003177 xmlChar *ret;
3178
3179 if ((reader == NULL) || (reader->node == NULL))
3180 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003181 if (reader->curnode != NULL)
3182 node = reader->curnode;
3183 else
3184 node = reader->node;
3185 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003186 case XML_ELEMENT_NODE:
3187 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003188 if ((node->ns == NULL) ||
3189 (node->ns->prefix == NULL))
3190 return(xmlStrdup(node->name));
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003191
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003192 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003193 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003194 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003195 return(ret);
3196 case XML_TEXT_NODE:
3197 return(xmlStrdup(BAD_CAST "#text"));
3198 case XML_CDATA_SECTION_NODE:
3199 return(xmlStrdup(BAD_CAST "#cdata-section"));
3200 case XML_ENTITY_NODE:
3201 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003202 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003203 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003204 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003205 case XML_COMMENT_NODE:
3206 return(xmlStrdup(BAD_CAST "#comment"));
3207 case XML_DOCUMENT_NODE:
3208 case XML_HTML_DOCUMENT_NODE:
3209#ifdef LIBXML_DOCB_ENABLED
3210 case XML_DOCB_DOCUMENT_NODE:
3211#endif
3212 return(xmlStrdup(BAD_CAST "#document"));
3213 case XML_DOCUMENT_FRAG_NODE:
3214 return(xmlStrdup(BAD_CAST "#document-fragment"));
3215 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003216 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003217 case XML_DOCUMENT_TYPE_NODE:
3218 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003219 return(xmlStrdup(node->name));
3220 case XML_NAMESPACE_DECL: {
3221 xmlNsPtr ns = (xmlNsPtr) node;
3222
3223 ret = xmlStrdup(BAD_CAST "xmlns");
3224 if (ns->prefix == NULL)
3225 return(ret);
3226 ret = xmlStrcat(ret, BAD_CAST ":");
3227 ret = xmlStrcat(ret, ns->prefix);
3228 return(ret);
3229 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003230
3231 case XML_ELEMENT_DECL:
3232 case XML_ATTRIBUTE_DECL:
3233 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003234 case XML_XINCLUDE_START:
3235 case XML_XINCLUDE_END:
3236 return(NULL);
3237 }
3238 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003239}
3240
3241/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003242 * xmlTextReaderConstName:
3243 * @reader: the xmlTextReaderPtr used
3244 *
3245 * The qualified name of the node, equal to Prefix :LocalName.
3246 *
3247 * Returns the local name or NULL if not available, the string is
3248 * deallocated with the reader.
3249 */
3250const xmlChar *
3251xmlTextReaderConstName(xmlTextReaderPtr reader) {
3252 xmlNodePtr node;
3253
3254 if ((reader == NULL) || (reader->node == NULL))
3255 return(NULL);
3256 if (reader->curnode != NULL)
3257 node = reader->curnode;
3258 else
3259 node = reader->node;
3260 switch (node->type) {
3261 case XML_ELEMENT_NODE:
3262 case XML_ATTRIBUTE_NODE:
3263 if ((node->ns == NULL) ||
3264 (node->ns->prefix == NULL))
3265 return(node->name);
3266 return(CONSTQSTR(node->ns->prefix, node->name));
3267 case XML_TEXT_NODE:
3268 return(CONSTSTR(BAD_CAST "#text"));
3269 case XML_CDATA_SECTION_NODE:
3270 return(CONSTSTR(BAD_CAST "#cdata-section"));
3271 case XML_ENTITY_NODE:
3272 case XML_ENTITY_REF_NODE:
3273 return(CONSTSTR(node->name));
3274 case XML_PI_NODE:
3275 return(CONSTSTR(node->name));
3276 case XML_COMMENT_NODE:
3277 return(CONSTSTR(BAD_CAST "#comment"));
3278 case XML_DOCUMENT_NODE:
3279 case XML_HTML_DOCUMENT_NODE:
3280#ifdef LIBXML_DOCB_ENABLED
3281 case XML_DOCB_DOCUMENT_NODE:
3282#endif
3283 return(CONSTSTR(BAD_CAST "#document"));
3284 case XML_DOCUMENT_FRAG_NODE:
3285 return(CONSTSTR(BAD_CAST "#document-fragment"));
3286 case XML_NOTATION_NODE:
3287 return(CONSTSTR(node->name));
3288 case XML_DOCUMENT_TYPE_NODE:
3289 case XML_DTD_NODE:
3290 return(CONSTSTR(node->name));
3291 case XML_NAMESPACE_DECL: {
3292 xmlNsPtr ns = (xmlNsPtr) node;
3293
3294 if (ns->prefix == NULL)
3295 return(CONSTSTR(BAD_CAST "xmlns"));
3296 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
3297 }
3298
3299 case XML_ELEMENT_DECL:
3300 case XML_ATTRIBUTE_DECL:
3301 case XML_ENTITY_DECL:
3302 case XML_XINCLUDE_START:
3303 case XML_XINCLUDE_END:
3304 return(NULL);
3305 }
3306 return(NULL);
3307}
3308
3309/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003310 * xmlTextReaderPrefix:
3311 * @reader: the xmlTextReaderPtr used
3312 *
3313 * A shorthand reference to the namespace associated with the node.
3314 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003315 * Returns the prefix or NULL if not available,
3316 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003317 */
3318xmlChar *
3319xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003320 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003321 if ((reader == NULL) || (reader->node == NULL))
3322 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003323 if (reader->curnode != NULL)
3324 node = reader->curnode;
3325 else
3326 node = reader->node;
3327 if (node->type == XML_NAMESPACE_DECL) {
3328 xmlNsPtr ns = (xmlNsPtr) node;
3329 if (ns->prefix == NULL)
3330 return(NULL);
3331 return(xmlStrdup(BAD_CAST "xmlns"));
3332 }
3333 if ((node->type != XML_ELEMENT_NODE) &&
3334 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003335 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00003336 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003337 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003338 return(NULL);
3339}
3340
3341/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003342 * xmlTextReaderConstPrefix:
3343 * @reader: the xmlTextReaderPtr used
3344 *
3345 * A shorthand reference to the namespace associated with the node.
3346 *
3347 * Returns the prefix or NULL if not available, the string is deallocated
3348 * with the reader.
3349 */
3350const xmlChar *
3351xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3352 xmlNodePtr node;
3353 if ((reader == NULL) || (reader->node == NULL))
3354 return(NULL);
3355 if (reader->curnode != NULL)
3356 node = reader->curnode;
3357 else
3358 node = reader->node;
3359 if (node->type == XML_NAMESPACE_DECL) {
3360 xmlNsPtr ns = (xmlNsPtr) node;
3361 if (ns->prefix == NULL)
3362 return(NULL);
3363 return(CONSTSTR(BAD_CAST "xmlns"));
3364 }
3365 if ((node->type != XML_ELEMENT_NODE) &&
3366 (node->type != XML_ATTRIBUTE_NODE))
3367 return(NULL);
3368 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3369 return(CONSTSTR(node->ns->prefix));
3370 return(NULL);
3371}
3372
3373/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003374 * xmlTextReaderNamespaceUri:
3375 * @reader: the xmlTextReaderPtr used
3376 *
3377 * The URI defining the namespace associated with the node.
3378 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003379 * Returns the namespace URI or NULL if not available,
3380 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003381 */
3382xmlChar *
3383xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003384 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003385 if ((reader == NULL) || (reader->node == NULL))
3386 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003387 if (reader->curnode != NULL)
3388 node = reader->curnode;
3389 else
3390 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00003391 if (node->type == XML_NAMESPACE_DECL)
3392 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003393 if ((node->type != XML_ELEMENT_NODE) &&
3394 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003395 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003396 if (node->ns != NULL)
3397 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003398 return(NULL);
3399}
3400
3401/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003402 * xmlTextReaderConstNamespaceUri:
3403 * @reader: the xmlTextReaderPtr used
3404 *
3405 * The URI defining the namespace associated with the node.
3406 *
3407 * Returns the namespace URI or NULL if not available, the string
3408 * will be deallocated with the reader
3409 */
3410const xmlChar *
3411xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3412 xmlNodePtr node;
3413 if ((reader == NULL) || (reader->node == NULL))
3414 return(NULL);
3415 if (reader->curnode != NULL)
3416 node = reader->curnode;
3417 else
3418 node = reader->node;
3419 if (node->type == XML_NAMESPACE_DECL)
3420 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3421 if ((node->type != XML_ELEMENT_NODE) &&
3422 (node->type != XML_ATTRIBUTE_NODE))
3423 return(NULL);
3424 if (node->ns != NULL)
3425 return(CONSTSTR(node->ns->href));
3426 return(NULL);
3427}
3428
3429/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003430 * xmlTextReaderBaseUri:
3431 * @reader: the xmlTextReaderPtr used
3432 *
3433 * The base URI of the node.
3434 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003435 * Returns the base URI or NULL if not available,
3436 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003437 */
3438xmlChar *
3439xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3440 if ((reader == NULL) || (reader->node == NULL))
3441 return(NULL);
3442 return(xmlNodeGetBase(NULL, reader->node));
3443}
3444
3445/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003446 * xmlTextReaderConstBaseUri:
3447 * @reader: the xmlTextReaderPtr used
3448 *
3449 * The base URI of the node.
3450 *
3451 * Returns the base URI or NULL if not available, the string
3452 * will be deallocated with the reader
3453 */
3454const xmlChar *
3455xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3456 xmlChar *tmp;
3457 const xmlChar *ret;
3458
3459 if ((reader == NULL) || (reader->node == NULL))
3460 return(NULL);
3461 tmp = xmlNodeGetBase(NULL, reader->node);
3462 if (tmp == NULL)
3463 return(NULL);
3464 ret = CONSTSTR(tmp);
3465 xmlFree(tmp);
3466 return(ret);
3467}
3468
3469/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003470 * xmlTextReaderDepth:
3471 * @reader: the xmlTextReaderPtr used
3472 *
3473 * The depth of the node in the tree.
3474 *
3475 * Returns the depth or -1 in case of error
3476 */
3477int
3478xmlTextReaderDepth(xmlTextReaderPtr reader) {
3479 if (reader == NULL)
3480 return(-1);
3481 if (reader->node == NULL)
3482 return(0);
3483
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003484 if (reader->curnode != NULL) {
3485 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3486 (reader->curnode->type == XML_NAMESPACE_DECL))
3487 return(reader->depth + 1);
3488 return(reader->depth + 2);
3489 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003490 return(reader->depth);
3491}
3492
3493/**
3494 * xmlTextReaderHasAttributes:
3495 * @reader: the xmlTextReaderPtr used
3496 *
3497 * Whether the node has attributes.
3498 *
3499 * Returns 1 if true, 0 if false, and -1 in case or error
3500 */
3501int
3502xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003503 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003504 if (reader == NULL)
3505 return(-1);
3506 if (reader->node == NULL)
3507 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003508 if (reader->curnode != NULL)
3509 node = reader->curnode;
3510 else
3511 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003512
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003513 if ((node->type == XML_ELEMENT_NODE) &&
Daniel Veillard6bb3e862004-11-24 12:39:00 +00003514 ((node->properties != NULL) || (node->nsDef != NULL)))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003515 return(1);
3516 /* TODO: handle the xmlDecl */
3517 return(0);
3518}
3519
3520/**
3521 * xmlTextReaderHasValue:
3522 * @reader: the xmlTextReaderPtr used
3523 *
3524 * Whether the node can have a text value.
3525 *
3526 * Returns 1 if true, 0 if false, and -1 in case or error
3527 */
3528int
3529xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003530 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003531 if (reader == NULL)
3532 return(-1);
3533 if (reader->node == NULL)
3534 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003535 if (reader->curnode != NULL)
3536 node = reader->curnode;
3537 else
3538 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003539
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003540 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003541 case XML_ATTRIBUTE_NODE:
3542 case XML_TEXT_NODE:
3543 case XML_CDATA_SECTION_NODE:
3544 case XML_PI_NODE:
3545 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00003546 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003547 return(1);
3548 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003549 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003550 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003551 return(0);
3552}
3553
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003554/**
3555 * xmlTextReaderValue:
3556 * @reader: the xmlTextReaderPtr used
3557 *
3558 * Provides the text value of the node if present
3559 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003560 * Returns the string or NULL if not available. The result must be deallocated
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003561 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003562 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003563xmlChar *
3564xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003565 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003566 if (reader == NULL)
3567 return(NULL);
3568 if (reader->node == NULL)
3569 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003570 if (reader->curnode != NULL)
3571 node = reader->curnode;
3572 else
3573 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003574
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003575 switch (node->type) {
3576 case XML_NAMESPACE_DECL:
3577 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003578 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003579 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003580
3581 if (attr->parent != NULL)
3582 return (xmlNodeListGetString
3583 (attr->parent->doc, attr->children, 1));
3584 else
3585 return (xmlNodeListGetString(NULL, attr->children, 1));
3586 break;
3587 }
3588 case XML_TEXT_NODE:
3589 case XML_CDATA_SECTION_NODE:
3590 case XML_PI_NODE:
3591 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003592 if (node->content != NULL)
3593 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003594 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003595 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003596 }
3597 return(NULL);
3598}
3599
3600/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003601 * xmlTextReaderConstValue:
3602 * @reader: the xmlTextReaderPtr used
3603 *
3604 * Provides the text value of the node if present
3605 *
3606 * Returns the string or NULL if not available. The result will be
3607 * deallocated on the next Read() operation.
3608 */
3609const xmlChar *
3610xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3611 xmlNodePtr node;
3612 if (reader == NULL)
3613 return(NULL);
3614 if (reader->node == NULL)
3615 return(NULL);
3616 if (reader->curnode != NULL)
3617 node = reader->curnode;
3618 else
3619 node = reader->node;
3620
3621 switch (node->type) {
3622 case XML_NAMESPACE_DECL:
3623 return(((xmlNsPtr) node)->href);
3624 case XML_ATTRIBUTE_NODE:{
3625 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard213f1fe2015-04-14 17:41:48 +08003626 const xmlChar *ret;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003627
3628 if ((attr->children != NULL) &&
3629 (attr->children->type == XML_TEXT_NODE) &&
3630 (attr->children->next == NULL))
3631 return(attr->children->content);
3632 else {
Daniel Veillard8165a6b2004-07-01 11:20:33 +00003633 if (reader->buffer == NULL) {
Daniel Veillard8aebce32012-07-16 14:42:31 +08003634 reader->buffer = xmlBufCreateSize(100);
3635 if (reader->buffer == NULL) {
3636 xmlGenericError(xmlGenericErrorContext,
3637 "xmlTextReaderSetup : malloc failed\n");
3638 return (NULL);
3639 }
Daniel Veillard213f1fe2015-04-14 17:41:48 +08003640 xmlBufSetAllocationScheme(reader->buffer,
3641 XML_BUFFER_ALLOC_BOUNDED);
Daniel Veillard8aebce32012-07-16 14:42:31 +08003642 } else
3643 xmlBufEmpty(reader->buffer);
3644 xmlBufGetNodeContent(reader->buffer, node);
Daniel Veillard213f1fe2015-04-14 17:41:48 +08003645 ret = xmlBufContent(reader->buffer);
3646 if (ret == NULL) {
3647 /* error on the buffer best to reallocate */
3648 xmlBufFree(reader->buffer);
3649 reader->buffer = xmlBufCreateSize(100);
3650 xmlBufSetAllocationScheme(reader->buffer,
3651 XML_BUFFER_ALLOC_BOUNDED);
3652 ret = BAD_CAST "";
3653 }
3654 return(ret);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003655 }
3656 break;
3657 }
3658 case XML_TEXT_NODE:
3659 case XML_CDATA_SECTION_NODE:
3660 case XML_PI_NODE:
3661 case XML_COMMENT_NODE:
3662 return(node->content);
3663 default:
3664 break;
3665 }
3666 return(NULL);
3667}
3668
3669/**
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003670 * xmlTextReaderIsDefault:
3671 * @reader: the xmlTextReaderPtr used
3672 *
3673 * Whether an Attribute node was generated from the default value
3674 * defined in the DTD or schema.
3675 *
3676 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3677 */
3678int
3679xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3680 if (reader == NULL)
3681 return(-1);
3682 return(0);
3683}
3684
3685/**
3686 * xmlTextReaderQuoteChar:
3687 * @reader: the xmlTextReaderPtr used
3688 *
3689 * The quotation mark character used to enclose the value of an attribute.
3690 *
3691 * Returns " or ' and -1 in case of error
3692 */
3693int
3694xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3695 if (reader == NULL)
3696 return(-1);
3697 /* TODO maybe lookup the attribute value for " first */
3698 return((int) '"');
3699}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003700
3701/**
3702 * xmlTextReaderXmlLang:
3703 * @reader: the xmlTextReaderPtr used
3704 *
3705 * The xml:lang scope within which the node resides.
3706 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003707 * Returns the xml:lang value or NULL if none exists.,
3708 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003709 */
3710xmlChar *
3711xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3712 if (reader == NULL)
3713 return(NULL);
3714 if (reader->node == NULL)
3715 return(NULL);
3716 return(xmlNodeGetLang(reader->node));
3717}
3718
Daniel Veillard67df8092002-12-16 22:04:11 +00003719/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00003720 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00003721 * @reader: the xmlTextReaderPtr used
3722 *
3723 * The xml:lang scope within which the node resides.
3724 *
3725 * Returns the xml:lang value or NULL if none exists.
3726 */
3727const xmlChar *
3728xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3729 xmlChar *tmp;
3730 const xmlChar *ret;
3731
3732 if (reader == NULL)
3733 return(NULL);
3734 if (reader->node == NULL)
3735 return(NULL);
3736 tmp = xmlNodeGetLang(reader->node);
3737 if (tmp == NULL)
3738 return(NULL);
3739 ret = CONSTSTR(tmp);
3740 xmlFree(tmp);
3741 return(ret);
3742}
3743
3744/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00003745 * xmlTextReaderConstString:
3746 * @reader: the xmlTextReaderPtr used
3747 * @str: the string to intern.
3748 *
3749 * Get an interned string from the reader, allows for example to
3750 * speedup string name comparisons
3751 *
3752 * Returns an interned copy of the string or NULL in case of error. The
3753 * string will be deallocated with the reader.
3754 */
3755const xmlChar *
3756xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3757 if (reader == NULL)
3758 return(NULL);
3759 return(CONSTSTR(str));
3760}
3761
3762/**
Daniel Veillard67df8092002-12-16 22:04:11 +00003763 * xmlTextReaderNormalization:
3764 * @reader: the xmlTextReaderPtr used
3765 *
3766 * The value indicating whether to normalize white space and attribute values.
3767 * Since attribute value and end of line normalizations are a MUST in the XML
3768 * specification only the value true is accepted. The broken bahaviour of
3769 * accepting out of range character entities like &#0; is of course not
3770 * supported either.
3771 *
3772 * Returns 1 or -1 in case of error.
3773 */
3774int
3775xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3776 if (reader == NULL)
3777 return(-1);
3778 return(1);
3779}
3780
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003781/************************************************************************
3782 * *
3783 * Extensions to the base APIs *
3784 * *
3785 ************************************************************************/
3786
3787/**
3788 * xmlTextReaderSetParserProp:
3789 * @reader: the xmlTextReaderPtr used
3790 * @prop: the xmlParserProperties to set
3791 * @value: usually 0 or 1 to (de)activate it
3792 *
3793 * Change the parser processing behaviour by changing some of its internal
3794 * properties. Note that some properties can only be changed before any
3795 * read has been done.
3796 *
3797 * Returns 0 if the call was successful, or -1 in case of error
3798 */
3799int
3800xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3801 xmlParserProperties p = (xmlParserProperties) prop;
3802 xmlParserCtxtPtr ctxt;
3803
3804 if ((reader == NULL) || (reader->ctxt == NULL))
3805 return(-1);
3806 ctxt = reader->ctxt;
3807
3808 switch (p) {
3809 case XML_PARSER_LOADDTD:
3810 if (value != 0) {
3811 if (ctxt->loadsubset == 0) {
3812 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3813 return(-1);
3814 ctxt->loadsubset = XML_DETECT_IDS;
3815 }
3816 } else {
3817 ctxt->loadsubset = 0;
3818 }
3819 return(0);
3820 case XML_PARSER_DEFAULTATTRS:
3821 if (value != 0) {
3822 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3823 } else {
3824 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3825 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3826 }
3827 return(0);
3828 case XML_PARSER_VALIDATE:
3829 if (value != 0) {
3830 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003831 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003832 } else {
3833 ctxt->validate = 0;
3834 }
3835 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003836 case XML_PARSER_SUBST_ENTITIES:
3837 if (value != 0) {
3838 ctxt->replaceEntities = 1;
3839 } else {
3840 ctxt->replaceEntities = 0;
3841 }
3842 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003843 }
3844 return(-1);
3845}
3846
3847/**
3848 * xmlTextReaderGetParserProp:
3849 * @reader: the xmlTextReaderPtr used
3850 * @prop: the xmlParserProperties to get
3851 *
3852 * Read the parser internal property.
3853 *
3854 * Returns the value, usually 0 or 1, or -1 in case of error.
3855 */
3856int
3857xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3858 xmlParserProperties p = (xmlParserProperties) prop;
3859 xmlParserCtxtPtr ctxt;
3860
3861 if ((reader == NULL) || (reader->ctxt == NULL))
3862 return(-1);
3863 ctxt = reader->ctxt;
3864
3865 switch (p) {
3866 case XML_PARSER_LOADDTD:
3867 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3868 return(1);
3869 return(0);
3870 case XML_PARSER_DEFAULTATTRS:
3871 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3872 return(1);
3873 return(0);
3874 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003875 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003876 case XML_PARSER_SUBST_ENTITIES:
3877 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003878 }
3879 return(-1);
3880}
3881
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003882
Daniel Veillarde18fc182002-12-28 22:56:33 +00003883/**
Aleksey Sanind671e282005-01-03 21:58:59 +00003884 * xmlTextReaderGetParserLineNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003885 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003886 *
3887 * Provide the line number of the current parsing point.
3888 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003889 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003890 */
3891int
3892xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
3893{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003894 if ((reader == NULL) || (reader->ctxt == NULL) ||
3895 (reader->ctxt->input == NULL)) {
3896 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003897 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003898 return (reader->ctxt->input->line);
Aleksey Sanind671e282005-01-03 21:58:59 +00003899}
3900
3901/**
3902 * xmlTextReaderGetParserColumnNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003903 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003904 *
3905 * Provide the column number of the current parsing point.
3906 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003907 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003908 */
3909int
3910xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
3911{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003912 if ((reader == NULL) || (reader->ctxt == NULL) ||
3913 (reader->ctxt->input == NULL)) {
3914 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003915 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003916 return (reader->ctxt->input->col);
Aleksey Sanind671e282005-01-03 21:58:59 +00003917}
3918
3919/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003920 * xmlTextReaderCurrentNode:
3921 * @reader: the xmlTextReaderPtr used
3922 *
3923 * Hacking interface allowing to get the xmlNodePtr correponding to the
3924 * current node being accessed by the xmlTextReader. This is dangerous
3925 * because the underlying node may be destroyed on the next Reads.
3926 *
3927 * Returns the xmlNodePtr or NULL in case of error.
3928 */
3929xmlNodePtr
3930xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3931 if (reader == NULL)
3932 return(NULL);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003933
Daniel Veillarde18fc182002-12-28 22:56:33 +00003934 if (reader->curnode != NULL)
3935 return(reader->curnode);
3936 return(reader->node);
3937}
3938
3939/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003940 * xmlTextReaderPreserve:
3941 * @reader: the xmlTextReaderPtr used
3942 *
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003943 * This tells the XML Reader to preserve the current node.
3944 * The caller must also use xmlTextReaderCurrentDoc() to
3945 * keep an handle on the resulting document once parsing has finished
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003946 *
3947 * Returns the xmlNodePtr or NULL in case of error.
3948 */
3949xmlNodePtr
3950xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3951 xmlNodePtr cur, parent;
3952
3953 if (reader == NULL)
3954 return(NULL);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003955
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003956 if (reader->curnode != NULL)
3957 cur = reader->curnode;
3958 else
3959 cur = reader->node;
3960 if (cur == NULL)
3961 return(NULL);
Daniel Veillard1e906612003-12-05 14:57:46 +00003962
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003963 if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003964 cur->extra |= NODE_IS_PRESERVED;
3965 cur->extra |= NODE_IS_SPRESERVED;
3966 }
3967 reader->preserves++;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003968
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003969 parent = cur->parent;;
3970 while (parent != NULL) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003971 if (parent->type == XML_ELEMENT_NODE)
3972 parent->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003973 parent = parent->parent;
3974 }
3975 return(cur);
3976}
3977
Daniel Veillard1e906612003-12-05 14:57:46 +00003978#ifdef LIBXML_PATTERN_ENABLED
3979/**
3980 * xmlTextReaderPreservePattern:
3981 * @reader: the xmlTextReaderPtr used
3982 * @pattern: an XPath subset pattern
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003983 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003984 *
Daniel Veillard1e906612003-12-05 14:57:46 +00003985 * This tells the XML Reader to preserve all nodes matched by the
3986 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3987 * keep an handle on the resulting document once parsing has finished
3988 *
Nick Wellnhofer5a0ae662017-06-17 23:20:38 +02003989 * Returns a non-negative number in case of success and -1 in case of error
Daniel Veillard1e906612003-12-05 14:57:46 +00003990 */
3991int
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003992xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3993 const xmlChar **namespaces)
3994{
Daniel Veillard1e906612003-12-05 14:57:46 +00003995 xmlPatternPtr comp;
3996
3997 if ((reader == NULL) || (pattern == NULL))
3998 return(-1);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003999
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00004000 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
Daniel Veillard1e906612003-12-05 14:57:46 +00004001 if (comp == NULL)
4002 return(-1);
4003
4004 if (reader->patternMax <= 0) {
4005 reader->patternMax = 4;
4006 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
4007 sizeof(reader->patternTab[0]));
4008 if (reader->patternTab == NULL) {
4009 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
4010 return (-1);
4011 }
4012 }
4013 if (reader->patternNr >= reader->patternMax) {
4014 xmlPatternPtr *tmp;
4015 reader->patternMax *= 2;
4016 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
4017 reader->patternMax *
4018 sizeof(reader->patternTab[0]));
4019 if (tmp == NULL) {
4020 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4021 reader->patternMax /= 2;
4022 return (-1);
4023 }
4024 reader->patternTab = tmp;
4025 }
4026 reader->patternTab[reader->patternNr] = comp;
4027 return(reader->patternNr++);
4028}
4029#endif
4030
Daniel Veillard9ee35f32003-09-28 00:19:54 +00004031/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00004032 * xmlTextReaderCurrentDoc:
4033 * @reader: the xmlTextReaderPtr used
4034 *
4035 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004036 * current document being accessed by the xmlTextReader.
Daniel Veillard9ee35f32003-09-28 00:19:54 +00004037 * NOTE: as a result of this call, the reader will not destroy the
4038 * associated XML document and calling xmlFreeDoc() on the result
4039 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00004040 *
4041 * Returns the xmlDocPtr or NULL in case of error.
4042 */
4043xmlDocPtr
4044xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004045 if (reader == NULL)
4046 return(NULL);
4047 if (reader->doc != NULL)
4048 return(reader->doc);
Daniel Veillard14dad702008-03-14 14:29:40 +00004049 if ((reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00004050 return(NULL);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004051
Daniel Veillard9ee35f32003-09-28 00:19:54 +00004052 reader->preserve = 1;
Daniel Veillarde18fc182002-12-28 22:56:33 +00004053 return(reader->ctxt->myDoc);
4054}
4055
Daniel Veillard37fc84d2003-05-09 19:38:15 +00004056#ifdef LIBXML_SCHEMAS_ENABLED
David Kilzer4472c3a2016-05-13 15:13:17 +08004057static char *xmlTextReaderBuildMessage(const char *msg, va_list ap) LIBXML_ATTR_FORMAT(1,0);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004058
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004059static void XMLCDECL
David Kilzer4472c3a2016-05-13 15:13:17 +08004060xmlTextReaderValidityError(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004061
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004062static void XMLCDECL
David Kilzer4472c3a2016-05-13 15:13:17 +08004063xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
4064
4065static void XMLCDECL
4066xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
4067
4068static void XMLCDECL
4069xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004070
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004071static void XMLCDECL
4072xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004073{
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004074 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004075
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004076 char *str;
4077
4078 va_list ap;
4079
4080 va_start(ap, msg);
4081 str = xmlTextReaderBuildMessage(msg, ap);
4082 if (!reader->errorFunc) {
4083 xmlTextReaderValidityError(ctx, "%s", str);
4084 } else {
4085 reader->errorFunc(reader->errorFuncArg, str,
4086 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4087 NULL /* locator */ );
4088 }
4089 if (str != NULL)
4090 xmlFree(str);
4091 va_end(ap);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004092}
4093
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004094static void XMLCDECL
4095xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004096{
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004097 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004098
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004099 char *str;
4100
4101 va_list ap;
4102
4103 va_start(ap, msg);
4104 str = xmlTextReaderBuildMessage(msg, ap);
4105 if (!reader->errorFunc) {
4106 xmlTextReaderValidityWarning(ctx, "%s", str);
4107 } else {
4108 reader->errorFunc(reader->errorFuncArg, str,
4109 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4110 NULL /* locator */ );
4111 }
4112 if (str != NULL)
4113 xmlFree(str);
4114 va_end(ap);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004115}
4116
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004117static void
4118 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004119
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004120static void
4121xmlTextReaderValidityStructuredRelay(void *userData, xmlErrorPtr error)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004122{
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004123 xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004124
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004125 if (reader->sErrorFunc) {
4126 reader->sErrorFunc(reader->errorFuncArg, error);
4127 } else {
4128 xmlTextReaderStructuredError(reader, error);
4129 }
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004130}
Daniel Veillardf4e55762003-04-15 23:32:22 +00004131/**
Daniel Veillard33300b42003-04-17 09:09:19 +00004132 * xmlTextReaderRelaxNGSetSchema:
4133 * @reader: the xmlTextReaderPtr used
4134 * @schema: a precompiled RelaxNG schema
4135 *
4136 * Use RelaxNG to validate the document as it is processed.
4137 * Activation is only possible before the first Read().
4138 * if @schema is NULL, then RelaxNG validation is desactivated.
4139 @ The @schema should not be freed until the reader is deallocated
4140 * or its use has been deactivated.
4141 *
4142 * Returns 0 in case the RelaxNG validation could be (des)activated and
4143 * -1 in case of error.
4144 */
4145int
4146xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
Daniel Veillardce682bc2004-11-05 17:22:25 +00004147 if (reader == NULL)
4148 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00004149 if (schema == NULL) {
4150 if (reader->rngSchemas != NULL) {
4151 xmlRelaxNGFree(reader->rngSchemas);
4152 reader->rngSchemas = NULL;
4153 }
4154 if (reader->rngValidCtxt != NULL) {
Noam Postavsky15794992012-03-19 16:08:16 +08004155 if (! reader->rngPreserveCtxt)
4156 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
Daniel Veillard33300b42003-04-17 09:09:19 +00004157 reader->rngValidCtxt = NULL;
4158 }
Noam Postavsky15794992012-03-19 16:08:16 +08004159 reader->rngPreserveCtxt = 0;
Daniel Veillard33300b42003-04-17 09:09:19 +00004160 return(0);
4161 }
4162 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4163 return(-1);
4164 if (reader->rngSchemas != NULL) {
4165 xmlRelaxNGFree(reader->rngSchemas);
4166 reader->rngSchemas = NULL;
4167 }
4168 if (reader->rngValidCtxt != NULL) {
Noam Postavsky15794992012-03-19 16:08:16 +08004169 if (! reader->rngPreserveCtxt)
4170 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
Daniel Veillard33300b42003-04-17 09:09:19 +00004171 reader->rngValidCtxt = NULL;
4172 }
Noam Postavsky15794992012-03-19 16:08:16 +08004173 reader->rngPreserveCtxt = 0;
Daniel Veillard33300b42003-04-17 09:09:19 +00004174 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
4175 if (reader->rngValidCtxt == NULL)
4176 return(-1);
4177 if (reader->errorFunc != NULL) {
4178 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004179 xmlTextReaderValidityErrorRelay,
4180 xmlTextReaderValidityWarningRelay,
4181 reader);
4182 }
4183 if (reader->sErrorFunc != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004184 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004185 xmlTextReaderValidityStructuredRelay,
4186 reader);
Daniel Veillard33300b42003-04-17 09:09:19 +00004187 }
4188 reader->rngValidErrors = 0;
4189 reader->rngFullNode = NULL;
4190 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4191 return(0);
4192}
4193
4194/**
Daniel Veillard97fa5b32012-08-14 11:01:07 +08004195 * xmlTextReaderLocator:
4196 * @ctx: the xmlTextReaderPtr used
4197 * @file: returned file information
4198 * @line: returned line information
4199 *
4200 * Internal locator function for the readers
4201 *
4202 * Returns 0 in case the Schema validation could be (des)activated and
4203 * -1 in case of error.
4204 */
4205static int
4206xmlTextReaderLocator(void *ctx, const char **file, unsigned long *line) {
4207 xmlTextReaderPtr reader;
4208
4209 if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
4210 return(-1);
4211
4212 if (file != NULL)
4213 *file = NULL;
4214 if (line != NULL)
4215 *line = 0;
4216
4217 reader = (xmlTextReaderPtr) ctx;
4218 if ((reader->ctxt != NULL) && (reader->ctxt->input != NULL)) {
4219 if (file != NULL)
4220 *file = reader->ctxt->input->filename;
4221 if (line != NULL)
4222 *line = reader->ctxt->input->line;
4223 return(0);
4224 }
4225 if (reader->node != NULL) {
4226 long res;
4227 int ret = 0;
4228
4229 if (line != NULL) {
4230 res = xmlGetLineNo(reader->node);
4231 if (res > 0)
4232 *line = (unsigned long) res;
4233 else
4234 ret = -1;
4235 }
4236 if (file != NULL) {
4237 xmlDocPtr doc = reader->node->doc;
4238 if ((doc != NULL) && (doc->URL != NULL))
4239 *file = (const char *) doc->URL;
4240 else
4241 ret = -1;
4242 }
4243 return(ret);
4244 }
4245 return(-1);
4246}
4247
4248/**
Daniel Veillardf10ae122005-07-10 19:03:16 +00004249 * xmlTextReaderSetSchema:
4250 * @reader: the xmlTextReaderPtr used
4251 * @schema: a precompiled Schema schema
4252 *
4253 * Use XSD Schema to validate the document as it is processed.
4254 * Activation is only possible before the first Read().
4255 * if @schema is NULL, then Schema validation is desactivated.
4256 @ The @schema should not be freed until the reader is deallocated
4257 * or its use has been deactivated.
4258 *
4259 * Returns 0 in case the Schema validation could be (des)activated and
4260 * -1 in case of error.
4261 */
4262int
4263xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
4264 if (reader == NULL)
4265 return(-1);
4266 if (schema == NULL) {
4267 if (reader->xsdPlug != NULL) {
4268 xmlSchemaSAXUnplug(reader->xsdPlug);
4269 reader->xsdPlug = NULL;
4270 }
4271 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004272 if (! reader->xsdPreserveCtxt)
4273 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004274 reader->xsdValidCtxt = NULL;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004275 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004276 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004277 if (reader->xsdSchemas != NULL) {
4278 xmlSchemaFree(reader->xsdSchemas);
4279 reader->xsdSchemas = NULL;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004280 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004281 return(0);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004282 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004283 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4284 return(-1);
4285 if (reader->xsdPlug != NULL) {
4286 xmlSchemaSAXUnplug(reader->xsdPlug);
4287 reader->xsdPlug = NULL;
4288 }
4289 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004290 if (! reader->xsdPreserveCtxt)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004291 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004292 reader->xsdValidCtxt = NULL;
4293 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004294 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004295 if (reader->xsdSchemas != NULL) {
4296 xmlSchemaFree(reader->xsdSchemas);
4297 reader->xsdSchemas = NULL;
4298 }
4299 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
4300 if (reader->xsdValidCtxt == NULL) {
4301 xmlSchemaFree(reader->xsdSchemas);
4302 reader->xsdSchemas = NULL;
4303 return(-1);
4304 }
4305 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4306 &(reader->ctxt->sax),
4307 &(reader->ctxt->userData));
4308 if (reader->xsdPlug == NULL) {
4309 xmlSchemaFree(reader->xsdSchemas);
4310 reader->xsdSchemas = NULL;
4311 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4312 reader->xsdValidCtxt = NULL;
4313 return(-1);
4314 }
Daniel Veillard97fa5b32012-08-14 11:01:07 +08004315 xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4316 xmlTextReaderLocator,
4317 (void *) reader);
4318
Daniel Veillardf10ae122005-07-10 19:03:16 +00004319 if (reader->errorFunc != NULL) {
4320 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004321 xmlTextReaderValidityErrorRelay,
4322 xmlTextReaderValidityWarningRelay,
4323 reader);
4324 }
4325 if (reader->sErrorFunc != NULL) {
4326 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4327 xmlTextReaderValidityStructuredRelay,
4328 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004329 }
4330 reader->xsdValidErrors = 0;
4331 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4332 return(0);
4333}
4334
4335/**
Noam Postavsky15794992012-03-19 16:08:16 +08004336 * xmlTextReaderRelaxNGValidateInternal:
Daniel Veillardf4e55762003-04-15 23:32:22 +00004337 * @reader: the xmlTextReaderPtr used
4338 * @rng: the path to a RelaxNG schema or NULL
Noam Postavsky15794992012-03-19 16:08:16 +08004339 * @ctxt: the RelaxNG schema validation context or NULL
4340 * @options: options (not yet used)
Daniel Veillardf4e55762003-04-15 23:32:22 +00004341 *
4342 * Use RelaxNG to validate the document as it is processed.
4343 * Activation is only possible before the first Read().
Noam Postavsky15794992012-03-19 16:08:16 +08004344 * If both @rng and @ctxt are NULL, then RelaxNG validation is deactivated.
Daniel Veillardf4e55762003-04-15 23:32:22 +00004345 *
William M. Brackd46c1ca2007-02-08 23:34:34 +00004346 * Returns 0 in case the RelaxNG validation could be (de)activated and
Noam Postavsky15794992012-03-19 16:08:16 +08004347 * -1 in case of error.
Daniel Veillardf4e55762003-04-15 23:32:22 +00004348 */
Noam Postavsky15794992012-03-19 16:08:16 +08004349static int
4350xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader,
4351 const char *rng,
4352 xmlRelaxNGValidCtxtPtr ctxt,
4353 int options ATTRIBUTE_UNUSED)
4354{
Daniel Veillardf4e55762003-04-15 23:32:22 +00004355 if (reader == NULL)
Daniel Veillardf4e55762003-04-15 23:32:22 +00004356 return(-1);
Noam Postavsky15794992012-03-19 16:08:16 +08004357
4358 if ((rng != NULL) && (ctxt != NULL))
4359 return (-1);
4360
4361 if (((rng != NULL) || (ctxt != NULL)) &&
4362 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4363 (reader->ctxt == NULL)))
4364 return(-1);
4365
4366 /* Cleanup previous validation stuff. */
4367 if (reader->rngValidCtxt != NULL) {
4368 if ( !reader->rngPreserveCtxt)
4369 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4370 reader->rngValidCtxt = NULL;
4371 }
4372 reader->rngPreserveCtxt = 0;
Daniel Veillard33300b42003-04-17 09:09:19 +00004373 if (reader->rngSchemas != NULL) {
4374 xmlRelaxNGFree(reader->rngSchemas);
4375 reader->rngSchemas = NULL;
4376 }
Noam Postavsky15794992012-03-19 16:08:16 +08004377
4378 if ((rng == NULL) && (ctxt == NULL)) {
4379 /* We just want to deactivate the validation, so get out. */
4380 return(0);
Daniel Veillard33300b42003-04-17 09:09:19 +00004381 }
Noam Postavsky15794992012-03-19 16:08:16 +08004382
4383
4384 if (rng != NULL) {
4385 xmlRelaxNGParserCtxtPtr pctxt;
4386 /* Parse the schema and create validation environment. */
4387
4388 pctxt = xmlRelaxNGNewParserCtxt(rng);
4389 if (reader->errorFunc != NULL) {
4390 xmlRelaxNGSetParserErrors(pctxt,
4391 xmlTextReaderValidityErrorRelay,
4392 xmlTextReaderValidityWarningRelay,
4393 reader);
4394 }
4395 if (reader->sErrorFunc != NULL) {
4396 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4397 xmlTextReaderValidityStructuredRelay,
4398 reader);
4399 }
4400 reader->rngSchemas = xmlRelaxNGParse(pctxt);
4401 xmlRelaxNGFreeParserCtxt(pctxt);
4402 if (reader->rngSchemas == NULL)
4403 return(-1);
4404 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
4405 if (reader->rngValidCtxt == NULL) {
4406 xmlRelaxNGFree(reader->rngSchemas);
4407 reader->rngSchemas = NULL;
4408 return(-1);
4409 }
4410 } else {
4411 /* Use the given validation context. */
4412 reader->rngValidCtxt = ctxt;
4413 reader->rngPreserveCtxt = 1;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004414 }
Noam Postavsky15794992012-03-19 16:08:16 +08004415 /*
4416 * Redirect the validation context's error channels to use
4417 * the reader channels.
4418 * TODO: In case the user provides the validation context we
4419 * could make this redirection optional.
4420 */
Daniel Veillardf4e55762003-04-15 23:32:22 +00004421 if (reader->errorFunc != NULL) {
4422 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004423 xmlTextReaderValidityErrorRelay,
4424 xmlTextReaderValidityWarningRelay,
4425 reader);
4426 }
4427 if (reader->sErrorFunc != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004428 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004429 xmlTextReaderValidityStructuredRelay,
4430 reader);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004431 }
4432 reader->rngValidErrors = 0;
4433 reader->rngFullNode = NULL;
4434 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4435 return(0);
4436}
Daniel Veillardf10ae122005-07-10 19:03:16 +00004437
4438/**
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004439 * xmlTextReaderSchemaValidateInternal:
Daniel Veillardf10ae122005-07-10 19:03:16 +00004440 * @reader: the xmlTextReaderPtr used
4441 * @xsd: the path to a W3C XSD schema or NULL
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004442 * @ctxt: the XML Schema validation context or NULL
4443 * @options: options (not used yet)
Daniel Veillardf10ae122005-07-10 19:03:16 +00004444 *
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004445 * Validate the document as it is processed using XML Schema.
Daniel Veillardf10ae122005-07-10 19:03:16 +00004446 * Activation is only possible before the first Read().
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004447 * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated.
Daniel Veillardf10ae122005-07-10 19:03:16 +00004448 *
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004449 * Returns 0 in case the schemas validation could be (de)activated and
Daniel Veillardf10ae122005-07-10 19:03:16 +00004450 * -1 in case of error.
4451 */
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004452static int
4453xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
4454 const char *xsd,
4455 xmlSchemaValidCtxtPtr ctxt,
4456 int options ATTRIBUTE_UNUSED)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004457{
Daniel Veillardf10ae122005-07-10 19:03:16 +00004458 if (reader == NULL)
4459 return(-1);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004460
4461 if ((xsd != NULL) && (ctxt != NULL))
Daniel Veillardf10ae122005-07-10 19:03:16 +00004462 return(-1);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004463
4464 if (((xsd != NULL) || (ctxt != NULL)) &&
4465 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4466 (reader->ctxt == NULL)))
4467 return(-1);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004468
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004469 /* Cleanup previous validation stuff. */
Daniel Veillardf10ae122005-07-10 19:03:16 +00004470 if (reader->xsdPlug != NULL) {
4471 xmlSchemaSAXUnplug(reader->xsdPlug);
4472 reader->xsdPlug = NULL;
4473 }
4474 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004475 if (! reader->xsdPreserveCtxt)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004476 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004477 reader->xsdValidCtxt = NULL;
4478 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004479 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004480 if (reader->xsdSchemas != NULL) {
4481 xmlSchemaFree(reader->xsdSchemas);
4482 reader->xsdSchemas = NULL;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004483 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004484
4485 if ((xsd == NULL) && (ctxt == NULL)) {
4486 /* We just want to deactivate the validation, so get out. */
4487 return(0);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004488 }
4489
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004490 if (xsd != NULL) {
4491 xmlSchemaParserCtxtPtr pctxt;
4492 /* Parse the schema and create validation environment. */
4493 pctxt = xmlSchemaNewParserCtxt(xsd);
4494 if (reader->errorFunc != NULL) {
4495 xmlSchemaSetParserErrors(pctxt,
4496 xmlTextReaderValidityErrorRelay,
4497 xmlTextReaderValidityWarningRelay,
4498 reader);
4499 }
4500 reader->xsdSchemas = xmlSchemaParse(pctxt);
4501 xmlSchemaFreeParserCtxt(pctxt);
4502 if (reader->xsdSchemas == NULL)
4503 return(-1);
4504 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4505 if (reader->xsdValidCtxt == NULL) {
4506 xmlSchemaFree(reader->xsdSchemas);
4507 reader->xsdSchemas = NULL;
4508 return(-1);
4509 }
4510 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4511 &(reader->ctxt->sax),
4512 &(reader->ctxt->userData));
4513 if (reader->xsdPlug == NULL) {
4514 xmlSchemaFree(reader->xsdSchemas);
4515 reader->xsdSchemas = NULL;
4516 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4517 reader->xsdValidCtxt = NULL;
4518 return(-1);
4519 }
4520 } else {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004521 /* Use the given validation context. */
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004522 reader->xsdValidCtxt = ctxt;
4523 reader->xsdPreserveCtxt = 1;
4524 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4525 &(reader->ctxt->sax),
4526 &(reader->ctxt->userData));
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004527 if (reader->xsdPlug == NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004528 reader->xsdValidCtxt = NULL;
4529 reader->xsdPreserveCtxt = 0;
4530 return(-1);
4531 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004532 }
Daniel Veillard97fa5b32012-08-14 11:01:07 +08004533 xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4534 xmlTextReaderLocator,
4535 (void *) reader);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004536 /*
4537 * Redirect the validation context's error channels to use
4538 * the reader channels.
4539 * TODO: In case the user provides the validation context we
4540 * could make this redirection optional.
4541 */
Daniel Veillardf10ae122005-07-10 19:03:16 +00004542 if (reader->errorFunc != NULL) {
4543 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004544 xmlTextReaderValidityErrorRelay,
4545 xmlTextReaderValidityWarningRelay,
4546 reader);
4547 }
4548 if (reader->sErrorFunc != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004549 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004550 xmlTextReaderValidityStructuredRelay,
4551 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004552 }
4553 reader->xsdValidErrors = 0;
4554 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4555 return(0);
4556}
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004557
4558/**
4559 * xmlTextReaderSchemaValidateCtxt:
4560 * @reader: the xmlTextReaderPtr used
4561 * @ctxt: the XML Schema validation context or NULL
4562 * @options: options (not used yet)
4563 *
4564 * Use W3C XSD schema context to validate the document as it is processed.
4565 * Activation is only possible before the first Read().
4566 * If @ctxt is NULL, then XML Schema validation is deactivated.
4567 *
4568 * Returns 0 in case the schemas validation could be (de)activated and
4569 * -1 in case of error.
4570 */
4571int
4572xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,
4573 xmlSchemaValidCtxtPtr ctxt,
4574 int options)
4575{
4576 return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options));
4577}
4578
4579/**
4580 * xmlTextReaderSchemaValidate:
4581 * @reader: the xmlTextReaderPtr used
4582 * @xsd: the path to a W3C XSD schema or NULL
4583 *
4584 * Use W3C XSD schema to validate the document as it is processed.
4585 * Activation is only possible before the first Read().
4586 * If @xsd is NULL, then XML Schema validation is deactivated.
4587 *
4588 * Returns 0 in case the schemas validation could be (de)activated and
4589 * -1 in case of error.
4590 */
4591int
4592xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd)
4593{
4594 return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));
4595}
Noam Postavsky15794992012-03-19 16:08:16 +08004596
4597/**
4598 * xmlTextReaderRelaxNGValidateCtxt:
4599 * @reader: the xmlTextReaderPtr used
4600 * @ctxt: the RelaxNG schema validation context or NULL
4601 * @options: options (not used yet)
4602 *
4603 * Use RelaxNG schema context to validate the document as it is processed.
4604 * Activation is only possible before the first Read().
4605 * If @ctxt is NULL, then RelaxNG schema validation is deactivated.
4606 *
4607 * Returns 0 in case the schemas validation could be (de)activated and
4608 * -1 in case of error.
4609 */
4610int
4611xmlTextReaderRelaxNGValidateCtxt(xmlTextReaderPtr reader,
4612 xmlRelaxNGValidCtxtPtr ctxt,
4613 int options)
4614{
4615 return(xmlTextReaderRelaxNGValidateInternal(reader, NULL, ctxt, options));
4616}
4617
4618/**
4619 * xmlTextReaderRelaxNGValidate:
4620 * @reader: the xmlTextReaderPtr used
4621 * @rng: the path to a RelaxNG schema or NULL
4622 *
4623 * Use RelaxNG schema to validate the document as it is processed.
4624 * Activation is only possible before the first Read().
4625 * If @rng is NULL, then RelaxNG schema validation is deactivated.
4626 *
4627 * Returns 0 in case the schemas validation could be (de)activated and
4628 * -1 in case of error.
4629 */
4630int
4631xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng)
4632{
4633 return(xmlTextReaderRelaxNGValidateInternal(reader, rng, NULL, 0));
4634}
4635
Daniel Veillard37fc84d2003-05-09 19:38:15 +00004636#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00004637
Daniel Veillarde2811272004-10-19 09:04:23 +00004638/**
4639 * xmlTextReaderIsNamespaceDecl:
4640 * @reader: the xmlTextReaderPtr used
4641 *
4642 * Determine whether the current node is a namespace declaration
4643 * rather than a regular attribute.
4644 *
4645 * Returns 1 if the current node is a namespace declaration, 0 if it
4646 * is a regular attribute or other type of node, or -1 in case of
4647 * error.
4648 */
4649int
4650xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4651 xmlNodePtr node;
4652 if (reader == NULL)
4653 return(-1);
4654 if (reader->node == NULL)
4655 return(-1);
4656 if (reader->curnode != NULL)
4657 node = reader->curnode;
4658 else
4659 node = reader->node;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004660
Daniel Veillarde2811272004-10-19 09:04:23 +00004661 if (XML_NAMESPACE_DECL == node->type)
4662 return(1);
4663 else
4664 return(0);
4665}
4666
4667/**
4668 * xmlTextReaderConstXmlVersion:
4669 * @reader: the xmlTextReaderPtr used
4670 *
4671 * Determine the XML version of the document being read.
4672 *
4673 * Returns a string containing the XML version of the document or NULL
4674 * in case of error. The string is deallocated with the reader.
4675 */
4676const xmlChar *
4677xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4678 xmlDocPtr doc = NULL;
4679 if (reader == NULL)
4680 return(NULL);
4681 if (reader->doc != NULL)
4682 doc = reader->doc;
4683 else if (reader->ctxt != NULL)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004684 doc = reader->ctxt->myDoc;
Daniel Veillarde2811272004-10-19 09:04:23 +00004685 if (doc == NULL)
4686 return(NULL);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004687
Daniel Veillarde2811272004-10-19 09:04:23 +00004688 if (doc->version == NULL)
4689 return(NULL);
4690 else
4691 return(CONSTSTR(doc->version));
4692}
4693
4694/**
4695 * xmlTextReaderStandalone:
4696 * @reader: the xmlTextReaderPtr used
4697 *
4698 * Determine the standalone status of the document being read.
4699 *
4700 * Returns 1 if the document was declared to be standalone, 0 if it
4701 * was declared to be not standalone, or -1 if the document did not
4702 * specify its standalone status or in case of error.
4703 */
4704int
4705xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4706 xmlDocPtr doc = NULL;
4707 if (reader == NULL)
4708 return(-1);
4709 if (reader->doc != NULL)
4710 doc = reader->doc;
4711 else if (reader->ctxt != NULL)
4712 doc = reader->ctxt->myDoc;
4713 if (doc == NULL)
4714 return(-1);
4715
4716 return(doc->standalone);
4717}
4718
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004719/************************************************************************
4720 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00004721 * Error Handling Extensions *
4722 * *
4723 ************************************************************************/
4724
4725/* helper to build a xmlMalloc'ed string from a format and va_list */
4726static char *
4727xmlTextReaderBuildMessage(const char *msg, va_list ap) {
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004728 int size = 0;
Daniel Veillard26f70262003-01-16 22:45:08 +00004729 int chars;
4730 char *larger;
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004731 char *str = NULL;
4732 va_list aq;
Daniel Veillard26f70262003-01-16 22:45:08 +00004733
4734 while (1) {
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004735 VA_COPY(aq, ap);
4736 chars = vsnprintf(str, size, msg, aq);
4737 va_end(aq);
4738 if (chars < 0) {
4739 xmlGenericError(xmlGenericErrorContext, "vsnprintf failed !\n");
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004740 if (str)
4741 xmlFree(str);
4742 return NULL;
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004743 }
4744 if ((chars < size) || (size == MAX_ERR_MSG_SIZE))
Daniel Veillard26f70262003-01-16 22:45:08 +00004745 break;
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004746 if (chars < MAX_ERR_MSG_SIZE)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004747 size = chars + 1;
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004748 else
4749 size = MAX_ERR_MSG_SIZE;
Daniel Veillard26f70262003-01-16 22:45:08 +00004750 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4751 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004752 if (str)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004753 xmlFree(str);
Daniel Veillard26f70262003-01-16 22:45:08 +00004754 return NULL;
4755 }
4756 str = larger;
4757 }
4758
4759 return str;
4760}
4761
Daniel Veillard417be3a2003-01-20 21:26:34 +00004762/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004763 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004764 * @locator: the xmlTextReaderLocatorPtr used
4765 *
4766 * Obtain the line number for the given locator.
4767 *
4768 * Returns the line number or -1 in case of error.
4769 */
4770int
4771xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4772 /* we know that locator is a xmlParserCtxtPtr */
4773 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4774 int ret = -1;
4775
Daniel Veillardce682bc2004-11-05 17:22:25 +00004776 if (locator == NULL)
4777 return(-1);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004778 if (ctx->node != NULL) {
4779 ret = xmlGetLineNo(ctx->node);
4780 }
4781 else {
4782 /* inspired from error.c */
4783 xmlParserInputPtr input;
4784 input = ctx->input;
4785 if ((input->filename == NULL) && (ctx->inputNr > 1))
4786 input = ctx->inputTab[ctx->inputNr - 2];
4787 if (input != NULL) {
4788 ret = input->line;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004789 }
Daniel Veillard417be3a2003-01-20 21:26:34 +00004790 else {
4791 ret = -1;
4792 }
4793 }
4794
4795 return ret;
4796}
4797
4798/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004799 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004800 * @locator: the xmlTextReaderLocatorPtr used
4801 *
4802 * Obtain the base URI for the given locator.
4803 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004804 * Returns the base URI or NULL in case of error,
4805 * if non NULL it need to be freed by the caller.
Daniel Veillard417be3a2003-01-20 21:26:34 +00004806 */
4807xmlChar *
4808xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4809 /* we know that locator is a xmlParserCtxtPtr */
4810 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4811 xmlChar *ret = NULL;
4812
Daniel Veillardce682bc2004-11-05 17:22:25 +00004813 if (locator == NULL)
4814 return(NULL);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004815 if (ctx->node != NULL) {
4816 ret = xmlNodeGetBase(NULL,ctx->node);
4817 }
4818 else {
4819 /* inspired from error.c */
4820 xmlParserInputPtr input;
4821 input = ctx->input;
4822 if ((input->filename == NULL) && (ctx->inputNr > 1))
4823 input = ctx->inputTab[ctx->inputNr - 2];
4824 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00004825 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004826 }
Daniel Veillard417be3a2003-01-20 21:26:34 +00004827 else {
4828 ret = NULL;
4829 }
4830 }
4831
4832 return ret;
4833}
4834
Daniel Veillard26f70262003-01-16 22:45:08 +00004835static void
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004836xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity,
4837 char *str)
4838{
4839 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4840
4841 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
Daniel Veillard26f70262003-01-16 22:45:08 +00004842
William M. Bracka3215c72004-07-31 16:24:01 +00004843 if (str != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004844 if (reader->errorFunc)
4845 reader->errorFunc(reader->errorFuncArg, str, severity,
4846 (xmlTextReaderLocatorPtr) ctx);
4847 xmlFree(str);
Daniel Veillard26f70262003-01-16 22:45:08 +00004848 }
4849}
4850
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004851static void
4852xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error)
4853{
4854 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
William M. Brack93d004f2004-02-03 00:14:10 +00004855
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004856 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4857
4858 if (error && reader->sErrorFunc) {
4859 reader->sErrorFunc(reader->errorFuncArg, (xmlErrorPtr) error);
4860 }
William M. Brack93d004f2004-02-03 00:14:10 +00004861}
4862
David Kilzer4472c3a2016-05-13 15:13:17 +08004863static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004864xmlTextReaderError(void *ctxt, const char *msg, ...)
4865{
Daniel Veillard26f70262003-01-16 22:45:08 +00004866 va_list ap;
4867
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004868 va_start(ap, msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004869 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004870 XML_PARSER_SEVERITY_ERROR,
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004871 xmlTextReaderBuildMessage(msg, ap));
Daniel Veillard26f70262003-01-16 22:45:08 +00004872 va_end(ap);
4873
4874}
4875
David Kilzer4472c3a2016-05-13 15:13:17 +08004876static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004877xmlTextReaderWarning(void *ctxt, const char *msg, ...)
4878{
Daniel Veillard26f70262003-01-16 22:45:08 +00004879 va_list ap;
4880
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004881 va_start(ap, msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004882 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004883 XML_PARSER_SEVERITY_WARNING,
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004884 xmlTextReaderBuildMessage(msg, ap));
Daniel Veillard26f70262003-01-16 22:45:08 +00004885 va_end(ap);
4886}
4887
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004888static void XMLCDECL
4889xmlTextReaderValidityError(void *ctxt, const char *msg, ...)
4890{
Daniel Veillard26f70262003-01-16 22:45:08 +00004891 va_list ap;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004892
Daniel Veillard417be3a2003-01-20 21:26:34 +00004893 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004894
Daniel Veillard417be3a2003-01-20 21:26:34 +00004895 if ((len > 1) && (msg[len - 2] != ':')) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004896 /*
4897 * some callbacks only report locator information:
4898 * skip them (mimicking behaviour in error.c)
4899 */
4900 va_start(ap, msg);
4901 xmlTextReaderGenericError(ctxt,
4902 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4903 xmlTextReaderBuildMessage(msg, ap));
4904 va_end(ap);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004905 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004906}
4907
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004908static void XMLCDECL
4909xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...)
4910{
Daniel Veillard26f70262003-01-16 22:45:08 +00004911 va_list ap;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004912
Daniel Veillard417be3a2003-01-20 21:26:34 +00004913 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004914
Daniel Veillard417be3a2003-01-20 21:26:34 +00004915 if ((len != 0) && (msg[len - 1] != ':')) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004916 /*
4917 * some callbacks only report locator information:
4918 * skip them (mimicking behaviour in error.c)
4919 */
4920 va_start(ap, msg);
4921 xmlTextReaderGenericError(ctxt,
4922 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4923 xmlTextReaderBuildMessage(msg, ap));
4924 va_end(ap);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004925 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004926}
4927
4928/**
4929 * xmlTextReaderSetErrorHandler:
4930 * @reader: the xmlTextReaderPtr used
4931 * @f: the callback function to call on error and warnings
4932 * @arg: a user argument to pass to the callback function
4933 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00004934 * Register a callback function that will be called on error and warnings.
4935 *
Daniel Veillard26f70262003-01-16 22:45:08 +00004936 * If @f is NULL, the default error and warning handlers are restored.
4937 */
4938void
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004939xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
4940 xmlTextReaderErrorFunc f, void *arg)
4941{
Daniel Veillard26f70262003-01-16 22:45:08 +00004942 if (f != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004943 reader->ctxt->sax->error = xmlTextReaderError;
4944 reader->ctxt->sax->serror = NULL;
4945 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4946 reader->ctxt->sax->warning = xmlTextReaderWarning;
4947 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4948 reader->errorFunc = f;
4949 reader->sErrorFunc = NULL;
4950 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004951#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004952 if (reader->rngValidCtxt) {
4953 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4954 xmlTextReaderValidityErrorRelay,
4955 xmlTextReaderValidityWarningRelay,
4956 reader);
4957 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4958 reader);
4959 }
4960 if (reader->xsdValidCtxt) {
4961 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4962 xmlTextReaderValidityErrorRelay,
4963 xmlTextReaderValidityWarningRelay,
4964 reader);
4965 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4966 reader);
4967 }
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004968#endif
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004969 } else {
4970 /* restore defaults */
4971 reader->ctxt->sax->error = xmlParserError;
4972 reader->ctxt->vctxt.error = xmlParserValidityError;
4973 reader->ctxt->sax->warning = xmlParserWarning;
4974 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4975 reader->errorFunc = NULL;
4976 reader->sErrorFunc = NULL;
4977 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004978#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004979 if (reader->rngValidCtxt) {
4980 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4981 reader);
4982 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4983 reader);
4984 }
4985 if (reader->xsdValidCtxt) {
4986 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4987 reader);
4988 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4989 reader);
4990 }
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004991#endif
Daniel Veillard26f70262003-01-16 22:45:08 +00004992 }
4993}
4994
Daniel Veillard417be3a2003-01-20 21:26:34 +00004995/**
William M. Brack93d004f2004-02-03 00:14:10 +00004996* xmlTextReaderSetStructuredErrorHandler:
4997 * @reader: the xmlTextReaderPtr used
4998 * @f: the callback function to call on error and warnings
4999 * @arg: a user argument to pass to the callback function
5000 *
5001 * Register a callback function that will be called on error and warnings.
5002 *
5003 * If @f is NULL, the default error and warning handlers are restored.
5004 */
5005void
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005006xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
5007 xmlStructuredErrorFunc f, void *arg)
5008{
5009 if (f != NULL) {
5010 reader->ctxt->sax->error = NULL;
5011 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
5012 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
5013 reader->ctxt->sax->warning = xmlTextReaderWarning;
5014 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
5015 reader->sErrorFunc = f;
5016 reader->errorFunc = NULL;
5017 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00005018#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005019 if (reader->rngValidCtxt) {
5020 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
5021 reader);
5022 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
5023 xmlTextReaderValidityStructuredRelay,
5024 reader);
5025 }
5026 if (reader->xsdValidCtxt) {
5027 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
5028 reader);
5029 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
5030 xmlTextReaderValidityStructuredRelay,
5031 reader);
5032 }
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00005033#endif
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005034 } else {
5035 /* restore defaults */
5036 reader->ctxt->sax->error = xmlParserError;
5037 reader->ctxt->sax->serror = NULL;
5038 reader->ctxt->vctxt.error = xmlParserValidityError;
5039 reader->ctxt->sax->warning = xmlParserWarning;
5040 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
5041 reader->errorFunc = NULL;
5042 reader->sErrorFunc = NULL;
5043 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00005044#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005045 if (reader->rngValidCtxt) {
5046 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
5047 reader);
5048 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
5049 reader);
5050 }
5051 if (reader->xsdValidCtxt) {
5052 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
5053 reader);
5054 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
5055 reader);
5056 }
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00005057#endif
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005058 }
William M. Brack93d004f2004-02-03 00:14:10 +00005059}
5060
5061/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00005062 * xmlTextReaderIsValid:
5063 * @reader: the xmlTextReaderPtr used
5064 *
5065 * Retrieve the validity status from the parser context
5066 *
5067 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
5068 */
5069int
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005070xmlTextReaderIsValid(xmlTextReaderPtr reader)
5071{
5072 if (reader == NULL)
5073 return (-1);
Daniel Veillardf4e55762003-04-15 23:32:22 +00005074#ifdef LIBXML_SCHEMAS_ENABLED
5075 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005076 return (reader->rngValidErrors == 0);
Daniel Veillardf10ae122005-07-10 19:03:16 +00005077 if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005078 return (reader->xsdValidErrors == 0);
Daniel Veillardf4e55762003-04-15 23:32:22 +00005079#endif
Daniel Veillard16ed5972003-11-20 18:22:31 +00005080 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005081 return (reader->ctxt->valid);
5082 return (0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00005083}
5084
5085/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00005086 * xmlTextReaderGetErrorHandler:
5087 * @reader: the xmlTextReaderPtr used
5088 * @f: the callback function or NULL is no callback has been registered
5089 * @arg: a user argument
5090 *
5091 * Retrieve the error callback function and user argument.
5092 */
Daniel Veillard26f70262003-01-16 22:45:08 +00005093void
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005094xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
5095 xmlTextReaderErrorFunc * f, void **arg)
5096{
5097 if (f != NULL)
5098 *f = reader->errorFunc;
5099 if (arg != NULL)
5100 *arg = reader->errorFuncArg;
Daniel Veillard26f70262003-01-16 22:45:08 +00005101}
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005102/************************************************************************
5103 * *
5104 * New set (2.6.0) of simpler and more flexible APIs *
5105 * *
5106 ************************************************************************/
5107
5108/**
5109 * xmlTextReaderSetup:
5110 * @reader: an XML reader
Daniel Veillarde96b47f2007-01-04 17:28:35 +00005111 * @input: xmlParserInputBufferPtr used to feed the reader, will
5112 * be destroyed with it.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005113 * @URL: the base URL to use for the document
5114 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005115 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005116 *
5117 * Setup an XML reader with new options
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005118 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005119 * Returns 0 in case of success and -1 in case of error.
5120 */
Aleksey Sanind8377642007-01-03 23:13:12 +00005121int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005122xmlTextReaderSetup(xmlTextReaderPtr reader,
5123 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005124 const char *encoding, int options)
5125{
William M. Brackd46c1ca2007-02-08 23:34:34 +00005126 if (reader == NULL) {
William M. Brackbf9a73d2007-02-09 00:07:07 +00005127 if (input != NULL)
William M. Brackd46c1ca2007-02-08 23:34:34 +00005128 xmlFreeParserInputBuffer(input);
William M. Brackbf9a73d2007-02-09 00:07:07 +00005129 return (-1);
William M. Brackd46c1ca2007-02-08 23:34:34 +00005130 }
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005131
Daniel Veillard8874b942005-08-25 13:19:21 +00005132 /*
5133 * we force the generation of compact text nodes on the reader
5134 * since usr applications should never modify the tree
5135 */
5136 options |= XML_PARSE_COMPACT;
5137
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005138 reader->doc = NULL;
5139 reader->entNr = 0;
Daniel Veillarde74d2e12003-12-09 11:35:37 +00005140 reader->parserFlags = options;
Daniel Veillardc36965d2003-12-02 10:28:48 +00005141 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005142 if ((input != NULL) && (reader->input != NULL) &&
5143 (reader->allocs & XML_TEXTREADER_INPUT)) {
5144 xmlFreeParserInputBuffer(reader->input);
5145 reader->input = NULL;
5146 reader->allocs -= XML_TEXTREADER_INPUT;
5147 }
5148 if (input != NULL) {
5149 reader->input = input;
5150 reader->allocs |= XML_TEXTREADER_INPUT;
5151 }
5152 if (reader->buffer == NULL)
Daniel Veillard8aebce32012-07-16 14:42:31 +08005153 reader->buffer = xmlBufCreateSize(100);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005154 if (reader->buffer == NULL) {
5155 xmlGenericError(xmlGenericErrorContext,
5156 "xmlTextReaderSetup : malloc failed\n");
5157 return (-1);
5158 }
Daniel Veillard213f1fe2015-04-14 17:41:48 +08005159 /* no operation on a reader should require a huge buffer */
5160 xmlBufSetAllocationScheme(reader->buffer,
5161 XML_BUFFER_ALLOC_BOUNDED);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005162 if (reader->sax == NULL)
5163 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
5164 if (reader->sax == NULL) {
5165 xmlGenericError(xmlGenericErrorContext,
5166 "xmlTextReaderSetup : malloc failed\n");
5167 return (-1);
5168 }
5169 xmlSAXVersion(reader->sax, 2);
5170 reader->startElement = reader->sax->startElement;
5171 reader->sax->startElement = xmlTextReaderStartElement;
5172 reader->endElement = reader->sax->endElement;
5173 reader->sax->endElement = xmlTextReaderEndElement;
5174#ifdef LIBXML_SAX1_ENABLED
5175 if (reader->sax->initialized == XML_SAX2_MAGIC) {
5176#endif /* LIBXML_SAX1_ENABLED */
5177 reader->startElementNs = reader->sax->startElementNs;
5178 reader->sax->startElementNs = xmlTextReaderStartElementNs;
5179 reader->endElementNs = reader->sax->endElementNs;
5180 reader->sax->endElementNs = xmlTextReaderEndElementNs;
5181#ifdef LIBXML_SAX1_ENABLED
5182 } else {
5183 reader->startElementNs = NULL;
5184 reader->endElementNs = NULL;
5185 }
5186#endif /* LIBXML_SAX1_ENABLED */
5187 reader->characters = reader->sax->characters;
5188 reader->sax->characters = xmlTextReaderCharacters;
5189 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
5190 reader->cdataBlock = reader->sax->cdataBlock;
5191 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
5192
5193 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5194 reader->node = NULL;
5195 reader->curnode = NULL;
5196 if (input != NULL) {
Daniel Veillard8aebce32012-07-16 14:42:31 +08005197 if (xmlBufUse(reader->input->buffer) < 4) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005198 xmlParserInputBufferRead(input, 4);
5199 }
5200 if (reader->ctxt == NULL) {
Daniel Veillard8aebce32012-07-16 14:42:31 +08005201 if (xmlBufUse(reader->input->buffer) >= 4) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005202 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
Daniel Veillard8aebce32012-07-16 14:42:31 +08005203 (const char *) xmlBufContent(reader->input->buffer),
5204 4, URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005205 reader->base = 0;
5206 reader->cur = 4;
5207 } else {
5208 reader->ctxt =
5209 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
5210 reader->base = 0;
5211 reader->cur = 0;
5212 }
5213 } else {
5214 xmlParserInputPtr inputStream;
5215 xmlParserInputBufferPtr buf;
5216 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
5217
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005218 xmlCtxtReset(reader->ctxt);
5219 buf = xmlAllocParserInputBuffer(enc);
5220 if (buf == NULL) return(-1);
5221 inputStream = xmlNewInputStream(reader->ctxt);
5222 if (inputStream == NULL) {
5223 xmlFreeParserInputBuffer(buf);
5224 return(-1);
5225 }
5226
5227 if (URL == NULL)
5228 inputStream->filename = NULL;
5229 else
5230 inputStream->filename = (char *)
5231 xmlCanonicPath((const xmlChar *) URL);
5232 inputStream->buf = buf;
Daniel Veillard61551a12012-07-16 16:28:47 +08005233 xmlBufResetInput(buf->buffer, inputStream);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005234
5235 inputPush(reader->ctxt, inputStream);
5236 reader->cur = 0;
5237 }
5238 if (reader->ctxt == NULL) {
5239 xmlGenericError(xmlGenericErrorContext,
5240 "xmlTextReaderSetup : malloc failed\n");
5241 return (-1);
5242 }
5243 }
5244 if (reader->dict != NULL) {
5245 if (reader->ctxt->dict != NULL) {
5246 if (reader->dict != reader->ctxt->dict) {
5247 xmlDictFree(reader->dict);
5248 reader->dict = reader->ctxt->dict;
5249 }
5250 } else {
5251 reader->ctxt->dict = reader->dict;
5252 }
5253 } else {
5254 if (reader->ctxt->dict == NULL)
5255 reader->ctxt->dict = xmlDictCreate();
5256 reader->dict = reader->ctxt->dict;
5257 }
5258 reader->ctxt->_private = reader;
5259 reader->ctxt->linenumbers = 1;
5260 reader->ctxt->dictNames = 1;
5261 /*
Jan Pokornýbb654fe2016-04-13 16:56:07 +02005262 * use the parser dictionary to allocate all elements and attributes names
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005263 */
5264 reader->ctxt->docdict = 1;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00005265 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005266
Daniel Veillard7899c5c2003-11-03 12:31:38 +00005267#ifdef LIBXML_XINCLUDE_ENABLED
5268 if (reader->xincctxt != NULL) {
5269 xmlXIncludeFreeContext(reader->xincctxt);
5270 reader->xincctxt = NULL;
5271 }
5272 if (options & XML_PARSE_XINCLUDE) {
5273 reader->xinclude = 1;
5274 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
5275 options -= XML_PARSE_XINCLUDE;
5276 } else
5277 reader->xinclude = 0;
5278 reader->in_xinclude = 0;
5279#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00005280#ifdef LIBXML_PATTERN_ENABLED
5281 if (reader->patternTab == NULL) {
5282 reader->patternNr = 0;
5283 reader->patternMax = 0;
5284 }
5285 while (reader->patternNr > 0) {
5286 reader->patternNr--;
5287 if (reader->patternTab[reader->patternNr] != NULL) {
5288 xmlFreePattern(reader->patternTab[reader->patternNr]);
5289 reader->patternTab[reader->patternNr] = NULL;
5290 }
5291 }
5292#endif
5293
Daniel Veillardc36965d2003-12-02 10:28:48 +00005294 if (options & XML_PARSE_DTDVALID)
5295 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
5296
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005297 xmlCtxtUseOptions(reader->ctxt, options);
5298 if (encoding != NULL) {
5299 xmlCharEncodingHandlerPtr hdlr;
5300
5301 hdlr = xmlFindCharEncodingHandler(encoding);
5302 if (hdlr != NULL)
5303 xmlSwitchToEncoding(reader->ctxt, hdlr);
5304 }
5305 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
5306 (reader->ctxt->input->filename == NULL))
5307 reader->ctxt->input->filename = (char *)
5308 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005309
5310 reader->doc = NULL;
5311
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005312 return (0);
5313}
5314
5315/**
Daniel Veillard5e094142005-02-18 19:36:12 +00005316 * xmlTextReaderByteConsumed:
5317 * @reader: an XML reader
5318 *
5319 * This function provides the current index of the parser used
5320 * by the reader, relative to the start of the current entity.
5321 * This function actually just wraps a call to xmlBytesConsumed()
5322 * for the parser context associated with the reader.
5323 * See xmlBytesConsumed() for more information.
5324 *
5325 * Returns the index in bytes from the beginning of the entity or -1
5326 * in case the index could not be computed.
5327 */
5328long
5329xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
5330 if ((reader == NULL) || (reader->ctxt == NULL))
5331 return(-1);
5332 return(xmlByteConsumed(reader->ctxt));
5333}
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005334
Daniel Veillard5e094142005-02-18 19:36:12 +00005335
5336/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005337 * xmlReaderWalker:
5338 * @doc: a preparsed document
5339 *
5340 * Create an xmltextReader for a preparsed document.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005341 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005342 * Returns the new reader or NULL in case of error.
5343 */
5344xmlTextReaderPtr
5345xmlReaderWalker(xmlDocPtr doc)
5346{
5347 xmlTextReaderPtr ret;
5348
5349 if (doc == NULL)
5350 return(NULL);
5351
5352 ret = xmlMalloc(sizeof(xmlTextReader));
5353 if (ret == NULL) {
5354 xmlGenericError(xmlGenericErrorContext,
5355 "xmlNewTextReader : malloc failed\n");
5356 return(NULL);
5357 }
5358 memset(ret, 0, sizeof(xmlTextReader));
5359 ret->entNr = 0;
5360 ret->input = NULL;
5361 ret->mode = XML_TEXTREADER_MODE_INITIAL;
5362 ret->node = NULL;
5363 ret->curnode = NULL;
5364 ret->base = 0;
5365 ret->cur = 0;
5366 ret->allocs = XML_TEXTREADER_CTXT;
5367 ret->doc = doc;
5368 ret->state = XML_TEXTREADER_START;
5369 ret->dict = xmlDictCreate();
5370 return(ret);
5371}
5372
5373/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005374 * xmlReaderForDoc:
5375 * @cur: a pointer to a zero terminated string
5376 * @URL: the base URL to use for the document
5377 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005378 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005379 *
5380 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005381 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005382 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005383 * Returns the new reader or NULL in case of error.
5384 */
5385xmlTextReaderPtr
5386xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
5387 int options)
5388{
5389 int len;
5390
5391 if (cur == NULL)
5392 return (NULL);
5393 len = xmlStrlen(cur);
5394
5395 return (xmlReaderForMemory
5396 ((const char *) cur, len, URL, encoding, options));
5397}
5398
5399/**
5400 * xmlReaderForFile:
5401 * @filename: a file or URL
5402 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005403 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005404 *
5405 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005406 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005407 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005408 * Returns the new reader or NULL in case of error.
5409 */
5410xmlTextReaderPtr
5411xmlReaderForFile(const char *filename, const char *encoding, int options)
5412{
5413 xmlTextReaderPtr reader;
5414
5415 reader = xmlNewTextReaderFilename(filename);
5416 if (reader == NULL)
5417 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005418 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005419 return (reader);
5420}
5421
5422/**
5423 * xmlReaderForMemory:
5424 * @buffer: a pointer to a char array
5425 * @size: the size of the array
5426 * @URL: the base URL to use for the document
5427 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005428 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005429 *
5430 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005431 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005432 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005433 * Returns the new reader or NULL in case of error.
5434 */
5435xmlTextReaderPtr
5436xmlReaderForMemory(const char *buffer, int size, const char *URL,
5437 const char *encoding, int options)
5438{
5439 xmlTextReaderPtr reader;
5440 xmlParserInputBufferPtr buf;
5441
Daniel Veillard21924522004-02-19 16:37:07 +00005442 buf = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005443 XML_CHAR_ENCODING_NONE);
5444 if (buf == NULL) {
5445 return (NULL);
5446 }
5447 reader = xmlNewTextReader(buf, URL);
5448 if (reader == NULL) {
5449 xmlFreeParserInputBuffer(buf);
5450 return (NULL);
5451 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005452 reader->allocs |= XML_TEXTREADER_INPUT;
5453 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005454 return (reader);
5455}
5456
5457/**
5458 * xmlReaderForFd:
5459 * @fd: an open file descriptor
5460 * @URL: the base URL to use for the document
5461 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005462 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005463 *
5464 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005465 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005466 * NOTE that the file descriptor will not be closed when the
5467 * reader is closed or reset.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005468 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005469 * Returns the new reader or NULL in case of error.
5470 */
5471xmlTextReaderPtr
5472xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
5473{
5474 xmlTextReaderPtr reader;
5475 xmlParserInputBufferPtr input;
5476
5477 if (fd < 0)
5478 return (NULL);
5479
5480 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5481 if (input == NULL)
5482 return (NULL);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005483 input->closecallback = NULL;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005484 reader = xmlNewTextReader(input, URL);
5485 if (reader == NULL) {
5486 xmlFreeParserInputBuffer(input);
5487 return (NULL);
5488 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005489 reader->allocs |= XML_TEXTREADER_INPUT;
5490 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005491 return (reader);
5492}
5493
5494/**
5495 * xmlReaderForIO:
5496 * @ioread: an I/O read function
5497 * @ioclose: an I/O close function
5498 * @ioctx: an I/O handler
5499 * @URL: the base URL to use for the document
5500 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005501 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005502 *
5503 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005504 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005505 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005506 * Returns the new reader or NULL in case of error.
5507 */
5508xmlTextReaderPtr
5509xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
5510 void *ioctx, const char *URL, const char *encoding,
5511 int options)
5512{
5513 xmlTextReaderPtr reader;
5514 xmlParserInputBufferPtr input;
5515
5516 if (ioread == NULL)
5517 return (NULL);
5518
5519 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5520 XML_CHAR_ENCODING_NONE);
Lin Yi-Li24464be2012-05-10 16:14:55 +08005521 if (input == NULL) {
5522 if (ioclose != NULL)
5523 ioclose(ioctx);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005524 return (NULL);
Lin Yi-Li24464be2012-05-10 16:14:55 +08005525 }
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005526 reader = xmlNewTextReader(input, URL);
5527 if (reader == NULL) {
5528 xmlFreeParserInputBuffer(input);
5529 return (NULL);
5530 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005531 reader->allocs |= XML_TEXTREADER_INPUT;
5532 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005533 return (reader);
5534}
5535
5536/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005537 * xmlReaderNewWalker:
5538 * @reader: an XML reader
5539 * @doc: a preparsed document
5540 *
5541 * Setup an xmltextReader to parse a preparsed XML document.
5542 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005543 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005544 * Returns 0 in case of success and -1 in case of error
5545 */
5546int
5547xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
5548{
5549 if (doc == NULL)
5550 return (-1);
5551 if (reader == NULL)
5552 return (-1);
5553
Daniel Veillarddd6d3002004-11-03 14:20:29 +00005554 if (reader->input != NULL) {
5555 xmlFreeParserInputBuffer(reader->input);
5556 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005557 if (reader->ctxt != NULL) {
5558 xmlCtxtReset(reader->ctxt);
5559 }
5560
5561 reader->entNr = 0;
5562 reader->input = NULL;
5563 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5564 reader->node = NULL;
5565 reader->curnode = NULL;
5566 reader->base = 0;
5567 reader->cur = 0;
5568 reader->allocs = XML_TEXTREADER_CTXT;
5569 reader->doc = doc;
5570 reader->state = XML_TEXTREADER_START;
5571 if (reader->dict == NULL) {
5572 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
5573 reader->dict = reader->ctxt->dict;
5574 else
5575 reader->dict = xmlDictCreate();
5576 }
5577 return(0);
5578}
5579
5580/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005581 * xmlReaderNewDoc:
5582 * @reader: an XML reader
5583 * @cur: a pointer to a zero terminated string
5584 * @URL: the base URL to use for the document
5585 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005586 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005587 *
5588 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005589 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005590 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005591 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005592 * Returns 0 in case of success and -1 in case of error
5593 */
5594int
5595xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
5596 const char *URL, const char *encoding, int options)
5597{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005598
5599 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005600
5601 if (cur == NULL)
5602 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005603 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005604 return (-1);
5605
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005606 len = xmlStrlen(cur);
5607 return (xmlReaderNewMemory(reader, (const char *)cur, len,
5608 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005609}
5610
5611/**
5612 * xmlReaderNewFile:
5613 * @reader: an XML reader
5614 * @filename: a file or URL
5615 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005616 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005617 *
5618 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005619 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005620 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005621 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005622 * Returns 0 in case of success and -1 in case of error
5623 */
5624int
5625xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
5626 const char *encoding, int options)
5627{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005628 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005629
5630 if (filename == NULL)
5631 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005632 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005633 return (-1);
5634
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005635 input =
5636 xmlParserInputBufferCreateFilename(filename,
5637 XML_CHAR_ENCODING_NONE);
5638 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005639 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005640 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005641}
5642
5643/**
5644 * xmlReaderNewMemory:
5645 * @reader: an XML reader
5646 * @buffer: a pointer to a char array
5647 * @size: the size of the array
5648 * @URL: the base URL to use for the document
5649 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005650 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005651 *
5652 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005653 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005654 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005655 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005656 * Returns 0 in case of success and -1 in case of error
5657 */
5658int
5659xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
5660 const char *URL, const char *encoding, int options)
5661{
5662 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005663
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005664 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005665 return (-1);
5666 if (buffer == NULL)
5667 return (-1);
5668
Daniel Veillard21924522004-02-19 16:37:07 +00005669 input = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005670 XML_CHAR_ENCODING_NONE);
5671 if (input == NULL) {
5672 return (-1);
5673 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005674 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005675}
5676
5677/**
5678 * xmlReaderNewFd:
5679 * @reader: an XML reader
5680 * @fd: an open file descriptor
5681 * @URL: the base URL to use for the document
5682 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005683 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005684 *
5685 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005686 * NOTE that the file descriptor will not be closed when the
5687 * reader is closed or reset.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005688 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005689 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005690 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005691 * Returns 0 in case of success and -1 in case of error
5692 */
5693int
5694xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
5695 const char *URL, const char *encoding, int options)
5696{
5697 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005698
5699 if (fd < 0)
5700 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005701 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005702 return (-1);
5703
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005704 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5705 if (input == NULL)
5706 return (-1);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005707 input->closecallback = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005708 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005709}
5710
5711/**
5712 * xmlReaderNewIO:
5713 * @reader: an XML reader
5714 * @ioread: an I/O read function
5715 * @ioclose: an I/O close function
5716 * @ioctx: an I/O handler
5717 * @URL: the base URL to use for the document
5718 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005719 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005720 *
5721 * Setup an xmltextReader to parse an XML document from I/O functions
5722 * and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005723 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005724 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005725 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005726 * Returns 0 in case of success and -1 in case of error
5727 */
5728int
5729xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
5730 xmlInputCloseCallback ioclose, void *ioctx,
5731 const char *URL, const char *encoding, int options)
5732{
5733 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005734
5735 if (ioread == NULL)
5736 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005737 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005738 return (-1);
5739
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005740 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5741 XML_CHAR_ENCODING_NONE);
Lin Yi-Li24464be2012-05-10 16:14:55 +08005742 if (input == NULL) {
5743 if (ioclose != NULL)
5744 ioclose(ioctx);
Daniel Veillard2c437da2012-05-11 12:08:15 +08005745 return (-1);
Lin Yi-Li24464be2012-05-10 16:14:55 +08005746 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005747 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005748}
Lin Yi-Li24464be2012-05-10 16:14:55 +08005749
Daniel Veillard26f70262003-01-16 22:45:08 +00005750/************************************************************************
5751 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005752 * Utilities *
5753 * *
5754 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005755#ifdef NOT_USED_YET
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005756
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005757/**
5758 * xmlBase64Decode:
5759 * @in: the input buffer
5760 * @inlen: the size of the input (in), the size read from it (out)
5761 * @to: the output buffer
5762 * @tolen: the size of the output (in), the size written to (out)
5763 *
5764 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00005765 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005766 *
5767 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
5768 * 2 if there wasn't enough space on the output or -1 in case of error.
5769 */
5770static int
5771xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005772 unsigned char *to, unsigned long *tolen)
5773{
5774 unsigned long incur; /* current index in in[] */
5775
5776 unsigned long inblk; /* last block index in in[] */
5777
5778 unsigned long outcur; /* current index in out[] */
5779
5780 unsigned long inmax; /* size of in[] */
5781
5782 unsigned long outmax; /* size of out[] */
5783
5784 unsigned char cur; /* the current value read from in[] */
5785
5786 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
5787
5788 int nbintmp; /* number of byte in intmp[] */
5789
5790 int is_ignore; /* cur should be ignored */
5791
5792 int is_end = 0; /* the end of the base64 was found */
5793
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005794 int retval = 1;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005795
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005796 int i;
5797
5798 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005799 return (-1);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005800
5801 incur = 0;
5802 inblk = 0;
5803 outcur = 0;
5804 inmax = *inlen;
5805 outmax = *tolen;
5806 nbintmp = 0;
5807
5808 while (1) {
5809 if (incur >= inmax)
5810 break;
5811 cur = in[incur++];
5812 is_ignore = 0;
5813 if ((cur >= 'A') && (cur <= 'Z'))
5814 cur = cur - 'A';
5815 else if ((cur >= 'a') && (cur <= 'z'))
5816 cur = cur - 'a' + 26;
5817 else if ((cur >= '0') && (cur <= '9'))
5818 cur = cur - '0' + 52;
5819 else if (cur == '+')
5820 cur = 62;
5821 else if (cur == '/')
5822 cur = 63;
5823 else if (cur == '.')
5824 cur = 0;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005825 else if (cur == '=') /*no op , end of the base64 stream */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005826 is_end = 1;
5827 else {
5828 is_ignore = 1;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005829 if (nbintmp == 0)
5830 inblk = incur;
5831 }
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005832
5833 if (!is_ignore) {
5834 int nbouttmp = 3;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005835
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005836 int is_break = 0;
5837
5838 if (is_end) {
5839 if (nbintmp == 0)
5840 break;
5841 if ((nbintmp == 1) || (nbintmp == 2))
5842 nbouttmp = 1;
5843 else
5844 nbouttmp = 2;
5845 nbintmp = 3;
5846 is_break = 1;
5847 }
5848 intmp[nbintmp++] = cur;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005849 /*
5850 * if intmp is full, push the 4byte sequence as a 3 byte
5851 * sequence out
5852 */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005853 if (nbintmp == 4) {
5854 nbintmp = 0;
5855 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
5856 outtmp[1] =
5857 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
5858 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005859 if (outcur + 3 >= outmax) {
5860 retval = 2;
5861 break;
5862 }
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005863
5864 for (i = 0; i < nbouttmp; i++)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005865 to[outcur++] = outtmp[i];
5866 inblk = incur;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005867 }
5868
5869 if (is_break) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005870 retval = 0;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005871 break;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005872 }
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005873 }
5874 }
5875
5876 *tolen = outcur;
5877 *inlen = inblk;
5878 return (retval);
5879}
5880
5881/*
5882 * Test routine for the xmlBase64Decode function
5883 */
5884#if 0
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005885int
5886main(int argc, char **argv)
5887{
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005888 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005889
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005890 char output[100];
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005891
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005892 char output2[100];
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005893
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005894 char output3[100];
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005895
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005896 unsigned long inlen = strlen(input);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005897
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005898 unsigned long outlen = 100;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005899
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005900 int ret;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005901
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005902 unsigned long cons, tmp, tmp2, prod;
5903
5904 /*
5905 * Direct
5906 */
5907 ret = xmlBase64Decode(input, &inlen, output, &outlen);
5908
5909 output[outlen] = 0;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005910 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen,
5911 outlen, output)indent: Standard input:179: Error:Unmatched #endif
5912;
5913
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005914 /*
5915 * output chunking
5916 */
5917 cons = 0;
5918 prod = 0;
5919 while (cons < inlen) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005920 tmp = 5;
5921 tmp2 = inlen - cons;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005922
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005923 printf("%ld %ld\n", cons, prod);
5924 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
5925 cons += tmp2;
5926 prod += tmp;
5927 printf("%ld %ld\n", cons, prod);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005928 }
5929 output2[outlen] = 0;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005930 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
5931 prod, output2);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005932
5933 /*
5934 * input chunking
5935 */
5936 cons = 0;
5937 prod = 0;
5938 while (cons < inlen) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005939 tmp = 100 - prod;
5940 tmp2 = inlen - cons;
5941 if (tmp2 > 5)
5942 tmp2 = 5;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005943
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005944 printf("%ld %ld\n", cons, prod);
5945 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
5946 cons += tmp2;
5947 prod += tmp;
5948 printf("%ld %ld\n", cons, prod);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005949 }
5950 output3[outlen] = 0;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005951 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
5952 prod, output3);
5953 return (0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005954
5955}
5956#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005957#endif /* NOT_USED_YET */
Daniel Veillard5d4644e2005-04-01 13:11:58 +00005958#define bottom_xmlreader
5959#include "elfgcchack.h"
Daniel Veillard81273902003-09-30 00:43:48 +00005960#endif /* LIBXML_READER_ENABLED */