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