blob: 00083d0e433bb8c9cf658c0da5422b3ce88e2b40 [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
Michael Woodfb27e2c2012-09-28 08:59:33 +0200987 * @len: length of the CData block in bytes.
Daniel Veillardf4e55762003-04-15 23:32:22 +0000988 *
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 Veillardeea38152013-01-28 16:55:30 +01001412 (reader->node->prev->type != XML_DTD_NODE)) {
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001413 xmlNodePtr tmp = reader->node->prev;
Daniel Veillarde8039df2003-10-27 11:25:13 +00001414 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001415 xmlUnlinkNode(tmp);
1416 xmlTextReaderFreeNode(reader, tmp);
1417 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001418 }
1419
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001420 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001421 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001422 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillard571b8892002-12-30 12:37:59 +00001423 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001424 (reader->node->children == NULL) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001425 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001426 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001427 goto node_found;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001428 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001429#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001430 if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001431 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001432#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001433 if ((reader->preserves > 0) &&
1434 (reader->node->extra & NODE_IS_SPRESERVED))
1435 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001436 reader->node = reader->node->parent;
1437 if ((reader->node == NULL) ||
1438 (reader->node->type == XML_DOCUMENT_NODE) ||
1439#ifdef LIBXML_DOCB_ENABLED
1440 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1441#endif
1442 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillarda9c56772007-03-09 16:59:05 +00001443 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001444 val = xmlParseChunk(reader->ctxt, "", 0, 1);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001445 reader->state = XML_TEXTREADER_DONE;
William M. Brack9f797ab2004-07-28 07:40:12 +00001446 if (val != 0)
1447 return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +00001448 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001449 reader->node = NULL;
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001450 reader->depth = -1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001451
1452 /*
1453 * Cleanup of the old node
1454 */
Daniel Veillard76d36452009-09-07 11:19:33 +02001455 if ((oldnode != NULL) && (reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001456#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001457 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001458#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001459 (reader->entNr == 0) &&
1460 (oldnode->type != XML_DTD_NODE) &&
Daniel Veillardeea38152013-01-28 16:55:30 +01001461 ((oldnode->extra & NODE_IS_PRESERVED) == 0)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001462 xmlUnlinkNode(oldnode);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001463 xmlTextReaderFreeNode(reader, oldnode);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001464 }
1465
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001466 goto node_end;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001467 }
Daniel Veillard1e906612003-12-05 14:57:46 +00001468 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001469#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001470 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001471#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001472 (reader->entNr == 0) &&
1473 (reader->node->last != NULL) &&
1474 ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1475 xmlNodePtr tmp = reader->node->last;
1476 xmlUnlinkNode(tmp);
1477 xmlTextReaderFreeNode(reader, tmp);
1478 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001479 reader->depth--;
1480 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001481
1482node_found:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001483 DUMP_READER
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001484
1485 /*
Daniel Veillarda880b122003-04-21 21:36:41 +00001486 * If we are in the middle of a piece of CDATA make sure it's finished
1487 */
1488 if ((reader->node != NULL) &&
Daniel Veillardccc4d2b2003-09-17 21:27:31 +00001489 (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001490 ((reader->node->type == XML_TEXT_NODE) ||
1491 (reader->node->type == XML_CDATA_SECTION_NODE))) {
William M. Brack42331a92004-07-29 07:07:16 +00001492 if (xmlTextReaderExpand(reader) == NULL)
1493 return -1;
Daniel Veillarda880b122003-04-21 21:36:41 +00001494 }
1495
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001496#ifdef LIBXML_XINCLUDE_ENABLED
1497 /*
1498 * Handle XInclude if asked for
1499 */
1500 if ((reader->xinclude) && (reader->node != NULL) &&
1501 (reader->node->type == XML_ELEMENT_NODE) &&
1502 (reader->node->ns != NULL) &&
Daniel Veillardb5fa0202003-12-08 17:41:29 +00001503 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1504 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001505 if (reader->xincctxt == NULL) {
1506 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001507 xmlXIncludeSetFlags(reader->xincctxt,
Daniel Veillardc14c3892004-08-16 12:34:50 +00001508 reader->parserFlags & (~XML_PARSE_NOXINCNODE));
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001509 }
1510 /*
1511 * expand that node and process it
1512 */
William M. Brack42331a92004-07-29 07:07:16 +00001513 if (xmlTextReaderExpand(reader) == NULL)
1514 return -1;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001515 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1516 }
Daniel Veillard11ce4002006-03-10 00:36:23 +00001517 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_START)) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001518 reader->in_xinclude++;
1519 goto get_next_node;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001520 }
Daniel Veillard11ce4002006-03-10 00:36:23 +00001521 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_END)) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001522 reader->in_xinclude--;
1523 goto get_next_node;
1524 }
1525#endif
Daniel Veillarda880b122003-04-21 21:36:41 +00001526 /*
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001527 * Handle entities enter and exit when in entity replacement mode
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001528 */
1529 if ((reader->node != NULL) &&
1530 (reader->node->type == XML_ENTITY_REF_NODE) &&
1531 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1532 /*
1533 * Case where the underlying tree is not availble, lookup the entity
1534 * and walk it.
1535 */
1536 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1537 (reader->ctxt->sax->getEntity != NULL)) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001538 reader->node->children = (xmlNodePtr)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001539 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1540 }
1541
1542 if ((reader->node->children != NULL) &&
1543 (reader->node->children->type == XML_ENTITY_DECL) &&
1544 (reader->node->children->children != NULL)) {
1545 xmlTextReaderEntPush(reader, reader->node);
1546 reader->node = reader->node->children->children;
1547 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001548#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001549 } else if ((reader->node != NULL) &&
1550 (reader->node->type == XML_ENTITY_REF_NODE) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001551 (reader->ctxt != NULL) && (reader->validate)) {
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001552 xmlTextReaderValidateEntity(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001553#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001554 }
1555 if ((reader->node != NULL) &&
1556 (reader->node->type == XML_ENTITY_DECL) &&
1557 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1558 reader->node = xmlTextReaderEntPop(reader);
1559 reader->depth++;
1560 goto get_next_node;
1561 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001562#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001563 if ((reader->validate) && (reader->node != NULL)) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001564 xmlNodePtr node = reader->node;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001565
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001566 if ((node->type == XML_ELEMENT_NODE) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001567 ((reader->state != XML_TEXTREADER_END) &&
1568 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1569 xmlTextReaderValidatePush(reader);
1570 } else if ((node->type == XML_TEXT_NODE) ||
1571 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001572 xmlTextReaderValidateCData(reader, node->content,
1573 xmlStrlen(node->content));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001574 }
1575 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001576#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001577#ifdef LIBXML_PATTERN_ENABLED
1578 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1579 (reader->state != XML_TEXTREADER_BACKTRACK)) {
1580 int i;
1581 for (i = 0;i < reader->patternNr;i++) {
1582 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1583 xmlTextReaderPreserve(reader);
1584 break;
1585 }
1586 }
1587 }
1588#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillardf10ae122005-07-10 19:03:16 +00001589#ifdef LIBXML_SCHEMAS_ENABLED
1590 if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) &&
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001591 (reader->xsdValidErrors == 0) &&
Daniel Veillardf10ae122005-07-10 19:03:16 +00001592 (reader->xsdValidCtxt != NULL)) {
1593 reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt);
1594 }
1595#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001596 return(1);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001597node_end:
Daniel Veillarda9c56772007-03-09 16:59:05 +00001598 reader->state = XML_TEXTREADER_DONE;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001599 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001600}
1601
Daniel Veillard67df8092002-12-16 22:04:11 +00001602/**
1603 * xmlTextReaderReadState:
1604 * @reader: the xmlTextReaderPtr used
1605 *
1606 * Gets the read state of the reader.
1607 *
1608 * Returns the state value, or -1 in case of error
1609 */
1610int
1611xmlTextReaderReadState(xmlTextReaderPtr reader) {
1612 if (reader == NULL)
1613 return(-1);
1614 return(reader->mode);
1615}
1616
1617/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001618 * xmlTextReaderExpand:
1619 * @reader: the xmlTextReaderPtr used
1620 *
1621 * Reads the contents of the current node and the full subtree. It then makes
Daniel Veillard61c52202003-04-30 12:20:34 +00001622 * the subtree available until the next xmlTextReaderRead() call
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001623 *
1624 * Returns a node pointer valid until the next xmlTextReaderRead() call
1625 * or NULL in case of error.
1626 */
1627xmlNodePtr
1628xmlTextReaderExpand(xmlTextReaderPtr reader) {
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001629 if ((reader == NULL) || (reader->node == NULL))
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001630 return(NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001631 if (reader->doc != NULL)
1632 return(reader->node);
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001633 if (reader->ctxt == NULL)
1634 return(NULL);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001635 if (xmlTextReaderDoExpand(reader) < 0)
1636 return(NULL);
1637 return(reader->node);
1638}
1639
1640/**
1641 * xmlTextReaderNext:
1642 * @reader: the xmlTextReaderPtr used
1643 *
1644 * Skip to the node following the current one in document order while
1645 * avoiding the subtree if any.
1646 *
1647 * Returns 1 if the node was read successfully, 0 if there is no more
1648 * nodes to read, or -1 in case of error
1649 */
1650int
1651xmlTextReaderNext(xmlTextReaderPtr reader) {
1652 int ret;
1653 xmlNodePtr cur;
1654
1655 if (reader == NULL)
1656 return(-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001657 if (reader->doc != NULL)
1658 return(xmlTextReaderNextTree(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001659 cur = reader->node;
1660 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1661 return(xmlTextReaderRead(reader));
Daniel Veillard5963aa72005-03-10 12:23:24 +00001662 if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001663 return(xmlTextReaderRead(reader));
Daniel Veillarde8039df2003-10-27 11:25:13 +00001664 if (cur->extra & NODE_IS_EMPTY)
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001665 return(xmlTextReaderRead(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001666 do {
1667 ret = xmlTextReaderRead(reader);
1668 if (ret != 1)
1669 return(ret);
1670 } while (reader->node != cur);
1671 return(xmlTextReaderRead(reader));
1672}
1673
Daniel Veillardd0271472006-01-02 10:22:02 +00001674#ifdef LIBXML_WRITER_ENABLED
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001675/**
Daniel Veillard67df8092002-12-16 22:04:11 +00001676 * xmlTextReaderReadInnerXml:
1677 * @reader: the xmlTextReaderPtr used
1678 *
1679 * Reads the contents of the current node, including child nodes and markup.
1680 *
1681 * Returns a string containing the XML content, or NULL if the current node
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001682 * is neither an element nor attribute, or has no child nodes. The
Daniel Veillard67df8092002-12-16 22:04:11 +00001683 * string must be deallocated by the caller.
1684 */
1685xmlChar *
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001686xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1687{
1688 xmlChar *resbuf;
1689 xmlNodePtr node, cur_node;
1690 xmlBufferPtr buff, buff2;
1691 xmlDocPtr doc;
1692
1693 if (xmlTextReaderExpand(reader) == NULL) {
1694 return NULL;
1695 }
1696 doc = reader->doc;
1697 buff = xmlBufferCreate();
1698 for (cur_node = reader->node->children; cur_node != NULL;
1699 cur_node = cur_node->next) {
1700 node = xmlDocCopyNode(cur_node, doc, 1);
1701 buff2 = xmlBufferCreate();
1702 if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
1703 xmlFreeNode(node);
1704 xmlBufferFree(buff2);
1705 xmlBufferFree(buff);
1706 return NULL;
1707 }
1708 xmlBufferCat(buff, buff2->content);
1709 xmlFreeNode(node);
1710 xmlBufferFree(buff2);
1711 }
1712 resbuf = buff->content;
Daniel Veillardbc4cc9d2005-12-12 13:26:56 +00001713 buff->content = NULL;
1714
1715 xmlBufferFree(buff);
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001716 return resbuf;
Daniel Veillard67df8092002-12-16 22:04:11 +00001717}
Daniel Veillardd0271472006-01-02 10:22:02 +00001718#endif
Daniel Veillard67df8092002-12-16 22:04:11 +00001719
Daniel Veillardd0271472006-01-02 10:22:02 +00001720#ifdef LIBXML_WRITER_ENABLED
Daniel Veillard67df8092002-12-16 22:04:11 +00001721/**
1722 * xmlTextReaderReadOuterXml:
1723 * @reader: the xmlTextReaderPtr used
1724 *
1725 * Reads the contents of the current node, including child nodes and markup.
1726 *
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001727 * Returns a string containing the node and any XML content, or NULL if the
1728 * current node cannot be serialized. The string must be deallocated
Rob Richards5b9dde32010-05-05 07:59:44 -04001729 * by the caller.
Daniel Veillard67df8092002-12-16 22:04:11 +00001730 */
1731xmlChar *
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001732xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1733{
1734 xmlChar *resbuf;
1735 xmlNodePtr node;
1736 xmlBufferPtr buff;
1737 xmlDocPtr doc;
1738
1739 node = reader->node;
1740 doc = reader->doc;
1741 if (xmlTextReaderExpand(reader) == NULL) {
1742 return NULL;
1743 }
Rob Richards5b9dde32010-05-05 07:59:44 -04001744 if (node->type == XML_DTD_NODE) {
1745 node = (xmlNodePtr) xmlCopyDtd((xmlDtdPtr) node);
1746 } else {
1747 node = xmlDocCopyNode(node, doc, 1);
1748 }
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001749 buff = xmlBufferCreate();
1750 if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
1751 xmlFreeNode(node);
1752 xmlBufferFree(buff);
1753 return NULL;
1754 }
1755
1756 resbuf = buff->content;
1757 buff->content = NULL;
1758
1759 xmlFreeNode(node);
1760 xmlBufferFree(buff);
1761 return resbuf;
Daniel Veillard67df8092002-12-16 22:04:11 +00001762}
Daniel Veillardd0271472006-01-02 10:22:02 +00001763#endif
Daniel Veillard67df8092002-12-16 22:04:11 +00001764
1765/**
1766 * xmlTextReaderReadString:
1767 * @reader: the xmlTextReaderPtr used
1768 *
1769 * Reads the contents of an element or a text node as a string.
1770 *
1771 * Returns a string containing the contents of the Element or Text node,
1772 * or NULL if the reader is positioned on any other type of node.
1773 * The string must be deallocated by the caller.
1774 */
1775xmlChar *
Daniel Veillarde125b312005-01-28 17:39:49 +00001776xmlTextReaderReadString(xmlTextReaderPtr reader)
1777{
1778 xmlNodePtr node;
1779
1780 if ((reader == NULL) || (reader->node == NULL))
1781 return(NULL);
1782
1783 node = (reader->curnode != NULL) ? reader->curnode : reader->node;
1784 switch (node->type) {
1785 case XML_TEXT_NODE:
1786 if (node->content != NULL)
1787 return(xmlStrdup(node->content));
1788 break;
1789 case XML_ELEMENT_NODE:
1790 if (xmlTextReaderDoExpand(reader) != -1) {
1791 return xmlTextReaderCollectSiblings(node->children);
1792 }
1793 case XML_ATTRIBUTE_NODE:
1794 TODO
1795 break;
1796 default:
1797 break;
1798 }
Daniel Veillard67df8092002-12-16 22:04:11 +00001799 return(NULL);
1800}
1801
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001802#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001803/**
1804 * xmlTextReaderReadBase64:
1805 * @reader: the xmlTextReaderPtr used
1806 * @array: a byte array to store the content.
1807 * @offset: the zero-based index into array where the method should
1808 * begin to write.
1809 * @len: the number of bytes to write.
1810 *
1811 * Reads and decodes the Base64 encoded contents of an element and
1812 * stores the result in a byte buffer.
1813 *
1814 * Returns the number of bytes written to array, or zero if the current
1815 * instance is not positioned on an element or -1 in case of error.
1816 */
1817int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001818xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1819 unsigned char *array ATTRIBUTE_UNUSED,
1820 int offset ATTRIBUTE_UNUSED,
1821 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001822 if ((reader == NULL) || (reader->ctxt == NULL))
1823 return(-1);
1824 if (reader->ctxt->wellFormed != 1)
1825 return(-1);
1826
1827 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1828 return(0);
1829 TODO
1830 return(0);
1831}
1832
1833/**
1834 * xmlTextReaderReadBinHex:
1835 * @reader: the xmlTextReaderPtr used
1836 * @array: a byte array to store the content.
1837 * @offset: the zero-based index into array where the method should
1838 * begin to write.
1839 * @len: the number of bytes to write.
1840 *
1841 * Reads and decodes the BinHex encoded contents of an element and
1842 * stores the result in a byte buffer.
1843 *
1844 * Returns the number of bytes written to array, or zero if the current
1845 * instance is not positioned on an element or -1 in case of error.
1846 */
1847int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001848xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1849 unsigned char *array ATTRIBUTE_UNUSED,
1850 int offset ATTRIBUTE_UNUSED,
1851 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001852 if ((reader == NULL) || (reader->ctxt == NULL))
1853 return(-1);
1854 if (reader->ctxt->wellFormed != 1)
1855 return(-1);
1856
1857 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1858 return(0);
1859 TODO
1860 return(0);
1861}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001862#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001863
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001864/************************************************************************
1865 * *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001866 * Operating on a preparsed tree *
1867 * *
1868 ************************************************************************/
1869static int
1870xmlTextReaderNextTree(xmlTextReaderPtr reader)
1871{
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001872 if (reader == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001873 return(-1);
1874
1875 if (reader->state == XML_TEXTREADER_END)
1876 return(0);
1877
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001878 if (reader->node == NULL) {
1879 if (reader->doc->children == NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001880 reader->state = XML_TEXTREADER_END;
1881 return(0);
1882 }
1883
1884 reader->node = reader->doc->children;
1885 reader->state = XML_TEXTREADER_START;
1886 return(1);
1887 }
1888
1889 if (reader->state != XML_TEXTREADER_BACKTRACK) {
Daniel Veillardbfa5cf12008-08-27 15:33:28 +00001890 /* Here removed traversal to child, because we want to skip the subtree,
Daniel Veillardaa6de472008-08-25 14:53:31 +00001891 replace with traversal to sibling to skip subtree */
1892 if (reader->node->next != 0) {
Daniel Veillardbfa5cf12008-08-27 15:33:28 +00001893 /* Move to sibling if present,skipping sub-tree */
1894 reader->node = reader->node->next;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001895 reader->state = XML_TEXTREADER_START;
1896 return(1);
1897 }
Daniel Veillardbfa5cf12008-08-27 15:33:28 +00001898
1899 /* if reader->node->next is NULL mean no subtree for current node,
Daniel Veillardaa6de472008-08-25 14:53:31 +00001900 so need to move to sibling of parent node if present */
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001901 if ((reader->node->type == XML_ELEMENT_NODE) ||
1902 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1903 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillardbfa5cf12008-08-27 15:33:28 +00001904 /* This will move to parent if present */
1905 xmlTextReaderRead(reader);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001906 }
1907 }
1908
1909 if (reader->node->next != 0) {
1910 reader->node = reader->node->next;
1911 reader->state = XML_TEXTREADER_START;
1912 return(1);
1913 }
1914
1915 if (reader->node->parent != 0) {
1916 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1917 reader->state = XML_TEXTREADER_END;
1918 return(0);
1919 }
1920
1921 reader->node = reader->node->parent;
1922 reader->depth--;
1923 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillardbfa5cf12008-08-27 15:33:28 +00001924 /* Repeat process to move to sibling of parent node if present */
1925 xmlTextReaderNextTree(reader);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001926 }
1927
1928 reader->state = XML_TEXTREADER_END;
1929
1930 return(1);
1931}
1932
1933/**
1934 * xmlTextReaderReadTree:
1935 * @reader: the xmlTextReaderPtr used
1936 *
1937 * Moves the position of the current instance to the next node in
1938 * the stream, exposing its properties.
1939 *
1940 * Returns 1 if the node was read successfully, 0 if there is no more
1941 * nodes to read, or -1 in case of error
1942 */
1943static int
1944xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1945 if (reader->state == XML_TEXTREADER_END)
1946 return(0);
1947
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001948next_node:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001949 if (reader->node == NULL) {
1950 if (reader->doc->children == NULL) {
1951 reader->state = XML_TEXTREADER_END;
1952 return(0);
1953 }
1954
1955 reader->node = reader->doc->children;
1956 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001957 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001958 }
1959
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001960 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1961 (reader->node->type != XML_DTD_NODE) &&
1962 (reader->node->type != XML_XINCLUDE_START) &&
1963 (reader->node->type != XML_ENTITY_REF_NODE)) {
1964 if (reader->node->children != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001965 reader->node = reader->node->children;
1966 reader->depth++;
1967 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001968 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001969 }
1970
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001971 if (reader->node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001972 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001973 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001974 }
1975 }
1976
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001977 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001978 reader->node = reader->node->next;
1979 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001980 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001981 }
1982
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001983 if (reader->node->parent != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001984 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1985 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1986 reader->state = XML_TEXTREADER_END;
1987 return(0);
1988 }
1989
1990 reader->node = reader->node->parent;
1991 reader->depth--;
1992 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001993 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001994 }
1995
1996 reader->state = XML_TEXTREADER_END;
1997
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001998found_node:
1999 if ((reader->node->type == XML_XINCLUDE_START) ||
2000 (reader->node->type == XML_XINCLUDE_END))
2001 goto next_node;
2002
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002003 return(1);
2004}
2005
2006/**
William M. Brackb1d53162003-11-18 06:54:40 +00002007 * xmlTextReaderNextSibling:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002008 * @reader: the xmlTextReaderPtr used
2009 *
2010 * Skip to the node following the current one in document order while
2011 * avoiding the subtree if any.
2012 * Currently implemented only for Readers built on a document
2013 *
2014 * Returns 1 if the node was read successfully, 0 if there is no more
2015 * nodes to read, or -1 in case of error
2016 */
2017int
2018xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
2019 if (reader == NULL)
2020 return(-1);
2021 if (reader->doc == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002022 /* TODO */
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002023 return(-1);
2024 }
2025
2026 if (reader->state == XML_TEXTREADER_END)
2027 return(0);
2028
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002029 if (reader->node == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002030 return(xmlTextReaderNextTree(reader));
2031
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002032 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002033 reader->node = reader->node->next;
2034 reader->state = XML_TEXTREADER_START;
2035 return(1);
2036 }
2037
2038 return(0);
2039}
2040
2041/************************************************************************
2042 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002043 * Constructor and destructors *
2044 * *
2045 ************************************************************************/
2046/**
2047 * xmlNewTextReader:
2048 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00002049 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002050 *
2051 * Create an xmlTextReader structure fed with @input
2052 *
2053 * Returns the new xmlTextReaderPtr or NULL in case of error
2054 */
2055xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00002056xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002057 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002058
2059 if (input == NULL)
2060 return(NULL);
2061 ret = xmlMalloc(sizeof(xmlTextReader));
2062 if (ret == NULL) {
2063 xmlGenericError(xmlGenericErrorContext,
2064 "xmlNewTextReader : malloc failed\n");
2065 return(NULL);
2066 }
2067 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002068 ret->doc = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002069 ret->entTab = NULL;
2070 ret->entMax = 0;
2071 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002072 ret->input = input;
Daniel Veillard8aebce32012-07-16 14:42:31 +08002073 ret->buffer = xmlBufCreateSize(100);
William M. Bracka3215c72004-07-31 16:24:01 +00002074 if (ret->buffer == NULL) {
2075 xmlFree(ret);
2076 xmlGenericError(xmlGenericErrorContext,
2077 "xmlNewTextReader : malloc failed\n");
2078 return(NULL);
2079 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002080 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
2081 if (ret->sax == NULL) {
Daniel Veillard8aebce32012-07-16 14:42:31 +08002082 xmlBufFree(ret->buffer);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002083 xmlFree(ret);
2084 xmlGenericError(xmlGenericErrorContext,
2085 "xmlNewTextReader : malloc failed\n");
2086 return(NULL);
2087 }
Daniel Veillard81273902003-09-30 00:43:48 +00002088 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002089 ret->startElement = ret->sax->startElement;
2090 ret->sax->startElement = xmlTextReaderStartElement;
2091 ret->endElement = ret->sax->endElement;
2092 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00002093#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002094 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00002095#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00002096 ret->startElementNs = ret->sax->startElementNs;
2097 ret->sax->startElementNs = xmlTextReaderStartElementNs;
2098 ret->endElementNs = ret->sax->endElementNs;
2099 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00002100#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002101 } else {
2102 ret->startElementNs = NULL;
2103 ret->endElementNs = NULL;
2104 }
Daniel Veillard81273902003-09-30 00:43:48 +00002105#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00002106 ret->characters = ret->sax->characters;
2107 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002108 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002109 ret->cdataBlock = ret->sax->cdataBlock;
2110 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002111
Daniel Veillard67df8092002-12-16 22:04:11 +00002112 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002113 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002114 ret->curnode = NULL;
Daniel Veillard8aebce32012-07-16 14:42:31 +08002115 if (xmlBufUse(ret->input->buffer) < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00002116 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00002117 }
Daniel Veillard8aebce32012-07-16 14:42:31 +08002118 if (xmlBufUse(ret->input->buffer) >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002119 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillard8aebce32012-07-16 14:42:31 +08002120 (const char *) xmlBufContent(ret->input->buffer),
2121 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002122 ret->base = 0;
2123 ret->cur = 4;
2124 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00002125 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002126 ret->base = 0;
2127 ret->cur = 0;
2128 }
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002129
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002130 if (ret->ctxt == NULL) {
2131 xmlGenericError(xmlGenericErrorContext,
2132 "xmlNewTextReader : malloc failed\n");
Daniel Veillard8aebce32012-07-16 14:42:31 +08002133 xmlBufFree(ret->buffer);
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002134 xmlFree(ret->sax);
2135 xmlFree(ret);
2136 return(NULL);
2137 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00002138 ret->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002139 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002140 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00002141 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002142 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002143 /*
2144 * use the parser dictionnary to allocate all elements and attributes names
2145 */
2146 ret->ctxt->docdict = 1;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002147 ret->dict = ret->ctxt->dict;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002148#ifdef LIBXML_XINCLUDE_ENABLED
2149 ret->xinclude = 0;
2150#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002151#ifdef LIBXML_PATTERN_ENABLED
2152 ret->patternMax = 0;
2153 ret->patternTab = NULL;
2154#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002155 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002156}
2157
2158/**
2159 * xmlNewTextReaderFilename:
2160 * @URI: the URI of the resource to process
2161 *
2162 * Create an xmlTextReader structure fed with the resource at @URI
2163 *
2164 * Returns the new xmlTextReaderPtr or NULL in case of error
2165 */
2166xmlTextReaderPtr
2167xmlNewTextReaderFilename(const char *URI) {
2168 xmlParserInputBufferPtr input;
2169 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002170 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002171
2172 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
2173 if (input == NULL)
2174 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00002175 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002176 if (ret == NULL) {
2177 xmlFreeParserInputBuffer(input);
2178 return(NULL);
2179 }
2180 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002181 if (ret->ctxt->directory == NULL)
2182 directory = xmlParserGetDirectory(URI);
2183 if ((ret->ctxt->directory == NULL) && (directory != NULL))
2184 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
2185 if (directory != NULL)
2186 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002187 return(ret);
2188}
2189
2190/**
2191 * xmlFreeTextReader:
2192 * @reader: the xmlTextReaderPtr
2193 *
2194 * Deallocate all the resources associated to the reader
2195 */
2196void
2197xmlFreeTextReader(xmlTextReaderPtr reader) {
2198 if (reader == NULL)
2199 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002200#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00002201 if (reader->rngSchemas != NULL) {
2202 xmlRelaxNGFree(reader->rngSchemas);
2203 reader->rngSchemas = NULL;
2204 }
2205 if (reader->rngValidCtxt != NULL) {
Noam Postavsky15794992012-03-19 16:08:16 +08002206 if (! reader->rngPreserveCtxt)
2207 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
Daniel Veillardf4e55762003-04-15 23:32:22 +00002208 reader->rngValidCtxt = NULL;
2209 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00002210 if (reader->xsdPlug != NULL) {
2211 xmlSchemaSAXUnplug(reader->xsdPlug);
2212 reader->xsdPlug = NULL;
2213 }
2214 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00002215 if (! reader->xsdPreserveCtxt)
2216 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00002217 reader->xsdValidCtxt = NULL;
2218 }
2219 if (reader->xsdSchemas != NULL) {
2220 xmlSchemaFree(reader->xsdSchemas);
2221 reader->xsdSchemas = NULL;
2222 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002223#endif
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002224#ifdef LIBXML_XINCLUDE_ENABLED
2225 if (reader->xincctxt != NULL)
2226 xmlXIncludeFreeContext(reader->xincctxt);
2227#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002228#ifdef LIBXML_PATTERN_ENABLED
2229 if (reader->patternTab != NULL) {
2230 int i;
2231 for (i = 0;i < reader->patternNr;i++) {
2232 if (reader->patternTab[i] != NULL)
2233 xmlFreePattern(reader->patternTab[i]);
2234 }
2235 xmlFree(reader->patternTab);
2236 }
2237#endif
Daniel Veillardf4653dc2009-08-21 18:40:50 +02002238 if (reader->faketext != NULL) {
2239 xmlFreeNode(reader->faketext);
2240 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002241 if (reader->ctxt != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002242 if (reader->dict == reader->ctxt->dict)
2243 reader->dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002244 if (reader->ctxt->myDoc != NULL) {
2245 if (reader->preserve == 0)
2246 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2247 reader->ctxt->myDoc = NULL;
2248 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002249 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2250 (reader->ctxt->vctxt.vstateMax > 0)){
2251 xmlFree(reader->ctxt->vctxt.vstateTab);
Daniel Veillard75e389d2005-07-29 22:02:24 +00002252 reader->ctxt->vctxt.vstateTab = NULL;
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002253 reader->ctxt->vctxt.vstateMax = 0;
2254 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002255 if (reader->allocs & XML_TEXTREADER_CTXT)
2256 xmlFreeParserCtxt(reader->ctxt);
2257 }
2258 if (reader->sax != NULL)
2259 xmlFree(reader->sax);
2260 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
2261 xmlFreeParserInputBuffer(reader->input);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002262 if (reader->buffer != NULL)
Daniel Veillard8aebce32012-07-16 14:42:31 +08002263 xmlBufFree(reader->buffer);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002264 if (reader->entTab != NULL)
2265 xmlFree(reader->entTab);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002266 if (reader->dict != NULL)
2267 xmlDictFree(reader->dict);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002268 xmlFree(reader);
2269}
2270
2271/************************************************************************
2272 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002273 * Methods for XmlTextReader *
2274 * *
2275 ************************************************************************/
2276/**
2277 * xmlTextReaderClose:
2278 * @reader: the xmlTextReaderPtr used
2279 *
2280 * This method releases any resources allocated by the current instance
2281 * changes the state to Closed and close any underlying input.
2282 *
2283 * Returns 0 or -1 in case of error
2284 */
2285int
2286xmlTextReaderClose(xmlTextReaderPtr reader) {
2287 if (reader == NULL)
2288 return(-1);
2289 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002290 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002291 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2292 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002293 xmlStopParser(reader->ctxt);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002294 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002295 if (reader->preserve == 0)
2296 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002297 reader->ctxt->myDoc = NULL;
2298 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002299 }
2300 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2301 xmlFreeParserInputBuffer(reader->input);
2302 reader->allocs -= XML_TEXTREADER_INPUT;
2303 }
2304 return(0);
2305}
2306
2307/**
2308 * xmlTextReaderGetAttributeNo:
2309 * @reader: the xmlTextReaderPtr used
2310 * @no: the zero-based index of the attribute relative to the containing element
2311 *
2312 * Provides the value of the attribute with the specified index relative
2313 * to the containing element.
2314 *
2315 * Returns a string containing the value of the specified attribute, or NULL
2316 * in case of error. The string must be deallocated by the caller.
2317 */
2318xmlChar *
2319xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2320 xmlChar *ret;
2321 int i;
2322 xmlAttrPtr cur;
2323 xmlNsPtr ns;
2324
2325 if (reader == NULL)
2326 return(NULL);
2327 if (reader->node == NULL)
2328 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002329 if (reader->curnode != NULL)
2330 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002331 /* TODO: handle the xmlDecl */
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002332 if (reader->node->type != XML_ELEMENT_NODE)
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002333 return(NULL);
2334
2335 ns = reader->node->nsDef;
2336 for (i = 0;(i < no) && (ns != NULL);i++) {
2337 ns = ns->next;
2338 }
2339 if (ns != NULL)
2340 return(xmlStrdup(ns->href));
2341
2342 cur = reader->node->properties;
2343 if (cur == NULL)
2344 return(NULL);
2345 for (;i < no;i++) {
2346 cur = cur->next;
2347 if (cur == NULL)
2348 return(NULL);
2349 }
2350 /* TODO walk the DTD if present */
2351
2352 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2353 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2354 return(ret);
2355}
2356
2357/**
2358 * xmlTextReaderGetAttribute:
2359 * @reader: the xmlTextReaderPtr used
2360 * @name: the qualified name of the attribute.
2361 *
2362 * Provides the value of the attribute with the specified qualified name.
2363 *
2364 * Returns a string containing the value of the specified attribute, or NULL
2365 * in case of error. The string must be deallocated by the caller.
2366 */
2367xmlChar *
2368xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2369 xmlChar *prefix = NULL;
2370 xmlChar *localname;
2371 xmlNsPtr ns;
2372 xmlChar *ret = NULL;
2373
2374 if ((reader == NULL) || (name == NULL))
2375 return(NULL);
2376 if (reader->node == NULL)
2377 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002378 if (reader->curnode != NULL)
2379 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002380
2381 /* TODO: handle the xmlDecl */
2382 if (reader->node->type != XML_ELEMENT_NODE)
2383 return(NULL);
2384
2385 localname = xmlSplitQName2(name, &prefix);
Daniel Veillard3c40e612005-08-17 07:07:44 +00002386 if (localname == NULL) {
2387 /*
2388 * Namespace default decl
2389 */
2390 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2391 ns = reader->node->nsDef;
2392 while (ns != NULL) {
2393 if (ns->prefix == NULL) {
2394 return(xmlStrdup(ns->href));
2395 }
2396 ns = ns->next;
2397 }
2398 return NULL;
2399 }
2400 return(xmlGetNoNsProp(reader->node, name));
2401 }
2402
2403 /*
2404 * Namespace default decl
2405 */
2406 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2407 ns = reader->node->nsDef;
2408 while (ns != NULL) {
2409 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2410 ret = xmlStrdup(ns->href);
2411 break;
2412 }
2413 ns = ns->next;
2414 }
2415 } else {
2416 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2417 if (ns != NULL)
2418 ret = xmlGetNsProp(reader->node, localname, ns->href);
2419 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002420
Daniel Veillardc4ff8322005-08-08 07:45:23 +00002421 xmlFree(localname);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002422 if (prefix != NULL)
2423 xmlFree(prefix);
2424 return(ret);
2425}
2426
2427
2428/**
2429 * xmlTextReaderGetAttributeNs:
2430 * @reader: the xmlTextReaderPtr used
2431 * @localName: the local name of the attribute.
2432 * @namespaceURI: the namespace URI of the attribute.
2433 *
2434 * Provides the value of the specified attribute
2435 *
2436 * Returns a string containing the value of the specified attribute, or NULL
2437 * in case of error. The string must be deallocated by the caller.
2438 */
2439xmlChar *
2440xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2441 const xmlChar *namespaceURI) {
Daniel Veillard45b97e72005-08-20 21:14:28 +00002442 xmlChar *prefix = NULL;
2443 xmlNsPtr ns;
2444
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002445 if ((reader == NULL) || (localName == NULL))
2446 return(NULL);
2447 if (reader->node == NULL)
2448 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002449 if (reader->curnode != NULL)
2450 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002451
2452 /* TODO: handle the xmlDecl */
2453 if (reader->node->type != XML_ELEMENT_NODE)
2454 return(NULL);
2455
Daniel Veillard45b97e72005-08-20 21:14:28 +00002456 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2457 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2458 prefix = BAD_CAST localName;
2459 }
2460 ns = reader->node->nsDef;
2461 while (ns != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002462 if ((prefix == NULL && ns->prefix == NULL) ||
Daniel Veillard45b97e72005-08-20 21:14:28 +00002463 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2464 return xmlStrdup(ns->href);
2465 }
2466 ns = ns->next;
2467 }
2468 return NULL;
2469 }
2470
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002471 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2472}
2473
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002474/**
2475 * xmlTextReaderGetRemainder:
2476 * @reader: the xmlTextReaderPtr used
2477 *
2478 * Method to get the remainder of the buffered XML. this method stops the
2479 * parser, set its state to End Of File and return the input stream with
2480 * what is left that the parser did not use.
2481 *
Daniel Veillardee1d6922004-04-18 14:58:57 +00002482 * The implementation is not good, the parser certainly procgressed past
2483 * what's left in reader->input, and there is an allocation problem. Best
2484 * would be to rewrite it differently.
2485 *
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002486 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2487 * in case of error.
2488 */
2489xmlParserInputBufferPtr
2490xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2491 xmlParserInputBufferPtr ret = NULL;
2492
2493 if (reader == NULL)
2494 return(NULL);
2495 if (reader->node == NULL)
2496 return(NULL);
2497
2498 reader->node = NULL;
2499 reader->curnode = NULL;
2500 reader->mode = XML_TEXTREADER_MODE_EOF;
2501 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002502 xmlStopParser(reader->ctxt);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002503 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002504 if (reader->preserve == 0)
2505 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002506 reader->ctxt->myDoc = NULL;
2507 }
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002508 }
2509 if (reader->allocs & XML_TEXTREADER_INPUT) {
2510 ret = reader->input;
Daniel Veillardee1d6922004-04-18 14:58:57 +00002511 reader->input = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002512 reader->allocs -= XML_TEXTREADER_INPUT;
2513 } else {
2514 /*
2515 * Hum, one may need to duplicate the data structure because
2516 * without reference counting the input may be freed twice:
2517 * - by the layer which allocated it.
2518 * - by the layer to which would have been returned to.
2519 */
2520 TODO
2521 return(NULL);
2522 }
2523 return(ret);
2524}
2525
2526/**
2527 * xmlTextReaderLookupNamespace:
2528 * @reader: the xmlTextReaderPtr used
2529 * @prefix: the prefix whose namespace URI is to be resolved. To return
2530 * the default namespace, specify NULL
2531 *
2532 * Resolves a namespace prefix in the scope of the current element.
2533 *
2534 * Returns a string containing the namespace URI to which the prefix maps
2535 * or NULL in case of error. The string must be deallocated by the caller.
2536 */
2537xmlChar *
2538xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2539 xmlNsPtr ns;
2540
2541 if (reader == NULL)
2542 return(NULL);
2543 if (reader->node == NULL)
2544 return(NULL);
2545
2546 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2547 if (ns == NULL)
2548 return(NULL);
2549 return(xmlStrdup(ns->href));
2550}
2551
2552/**
2553 * xmlTextReaderMoveToAttributeNo:
2554 * @reader: the xmlTextReaderPtr used
2555 * @no: the zero-based index of the attribute relative to the containing
2556 * element.
2557 *
2558 * Moves the position of the current instance to the attribute with
2559 * the specified index relative to the containing element.
2560 *
2561 * Returns 1 in case of success, -1 in case of error, 0 if not found
2562 */
2563int
2564xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2565 int i;
2566 xmlAttrPtr cur;
2567 xmlNsPtr ns;
2568
2569 if (reader == NULL)
2570 return(-1);
2571 if (reader->node == NULL)
2572 return(-1);
2573 /* TODO: handle the xmlDecl */
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002574 if (reader->node->type != XML_ELEMENT_NODE)
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002575 return(-1);
2576
2577 reader->curnode = NULL;
2578
2579 ns = reader->node->nsDef;
2580 for (i = 0;(i < no) && (ns != NULL);i++) {
2581 ns = ns->next;
2582 }
2583 if (ns != NULL) {
2584 reader->curnode = (xmlNodePtr) ns;
2585 return(1);
2586 }
2587
2588 cur = reader->node->properties;
2589 if (cur == NULL)
2590 return(0);
2591 for (;i < no;i++) {
2592 cur = cur->next;
2593 if (cur == NULL)
2594 return(0);
2595 }
2596 /* TODO walk the DTD if present */
2597
2598 reader->curnode = (xmlNodePtr) cur;
2599 return(1);
2600}
2601
2602/**
2603 * xmlTextReaderMoveToAttribute:
2604 * @reader: the xmlTextReaderPtr used
2605 * @name: the qualified name of the attribute.
2606 *
2607 * Moves the position of the current instance to the attribute with
2608 * the specified qualified name.
2609 *
2610 * Returns 1 in case of success, -1 in case of error, 0 if not found
2611 */
2612int
2613xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2614 xmlChar *prefix = NULL;
2615 xmlChar *localname;
2616 xmlNsPtr ns;
2617 xmlAttrPtr prop;
2618
2619 if ((reader == NULL) || (name == NULL))
2620 return(-1);
2621 if (reader->node == NULL)
2622 return(-1);
2623
2624 /* TODO: handle the xmlDecl */
2625 if (reader->node->type != XML_ELEMENT_NODE)
2626 return(0);
2627
2628 localname = xmlSplitQName2(name, &prefix);
2629 if (localname == NULL) {
2630 /*
2631 * Namespace default decl
2632 */
2633 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2634 ns = reader->node->nsDef;
2635 while (ns != NULL) {
2636 if (ns->prefix == NULL) {
2637 reader->curnode = (xmlNodePtr) ns;
2638 return(1);
2639 }
2640 ns = ns->next;
2641 }
2642 return(0);
2643 }
2644
2645 prop = reader->node->properties;
2646 while (prop != NULL) {
2647 /*
2648 * One need to have
2649 * - same attribute names
2650 * - and the attribute carrying that namespace
2651 */
2652 if ((xmlStrEqual(prop->name, name)) &&
2653 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2654 reader->curnode = (xmlNodePtr) prop;
2655 return(1);
2656 }
2657 prop = prop->next;
2658 }
2659 return(0);
2660 }
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002661
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002662 /*
2663 * Namespace default decl
2664 */
2665 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2666 ns = reader->node->nsDef;
2667 while (ns != NULL) {
2668 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2669 reader->curnode = (xmlNodePtr) ns;
2670 goto found;
2671 }
2672 ns = ns->next;
2673 }
2674 goto not_found;
2675 }
2676 prop = reader->node->properties;
2677 while (prop != NULL) {
2678 /*
2679 * One need to have
2680 * - same attribute names
2681 * - and the attribute carrying that namespace
2682 */
2683 if ((xmlStrEqual(prop->name, localname)) &&
2684 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2685 reader->curnode = (xmlNodePtr) prop;
2686 goto found;
2687 }
2688 prop = prop->next;
2689 }
2690not_found:
2691 if (localname != NULL)
2692 xmlFree(localname);
2693 if (prefix != NULL)
2694 xmlFree(prefix);
2695 return(0);
2696
2697found:
2698 if (localname != NULL)
2699 xmlFree(localname);
2700 if (prefix != NULL)
2701 xmlFree(prefix);
2702 return(1);
2703}
2704
2705/**
2706 * xmlTextReaderMoveToAttributeNs:
2707 * @reader: the xmlTextReaderPtr used
2708 * @localName: the local name of the attribute.
2709 * @namespaceURI: the namespace URI of the attribute.
2710 *
2711 * Moves the position of the current instance to the attribute with the
2712 * specified local name and namespace URI.
2713 *
2714 * Returns 1 in case of success, -1 in case of error, 0 if not found
2715 */
2716int
2717xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2718 const xmlChar *localName, const xmlChar *namespaceURI) {
2719 xmlAttrPtr prop;
2720 xmlNodePtr node;
Daniel Veillard45b97e72005-08-20 21:14:28 +00002721 xmlNsPtr ns;
2722 xmlChar *prefix = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002723
2724 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2725 return(-1);
2726 if (reader->node == NULL)
2727 return(-1);
2728 if (reader->node->type != XML_ELEMENT_NODE)
2729 return(0);
2730 node = reader->node;
2731
Daniel Veillard45b97e72005-08-20 21:14:28 +00002732 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2733 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2734 prefix = BAD_CAST localName;
2735 }
2736 ns = reader->node->nsDef;
2737 while (ns != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002738 if ((prefix == NULL && ns->prefix == NULL) ||
Daniel Veillard45b97e72005-08-20 21:14:28 +00002739 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2740 reader->curnode = (xmlNodePtr) ns;
2741 return(1);
2742 }
2743 ns = ns->next;
2744 }
2745 return(0);
2746 }
2747
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002748 prop = node->properties;
2749 while (prop != NULL) {
2750 /*
2751 * One need to have
2752 * - same attribute names
2753 * - and the attribute carrying that namespace
2754 */
2755 if (xmlStrEqual(prop->name, localName) &&
2756 ((prop->ns != NULL) &&
2757 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2758 reader->curnode = (xmlNodePtr) prop;
2759 return(1);
2760 }
2761 prop = prop->next;
2762 }
2763 return(0);
2764}
2765
2766/**
2767 * xmlTextReaderMoveToFirstAttribute:
2768 * @reader: the xmlTextReaderPtr used
2769 *
2770 * Moves the position of the current instance to the first attribute
2771 * associated with the current node.
2772 *
2773 * Returns 1 in case of success, -1 in case of error, 0 if not found
2774 */
2775int
2776xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2777 if (reader == NULL)
2778 return(-1);
2779 if (reader->node == NULL)
2780 return(-1);
2781 if (reader->node->type != XML_ELEMENT_NODE)
2782 return(0);
2783
2784 if (reader->node->nsDef != NULL) {
2785 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2786 return(1);
2787 }
2788 if (reader->node->properties != NULL) {
2789 reader->curnode = (xmlNodePtr) reader->node->properties;
2790 return(1);
2791 }
2792 return(0);
2793}
2794
2795/**
2796 * xmlTextReaderMoveToNextAttribute:
2797 * @reader: the xmlTextReaderPtr used
2798 *
2799 * Moves the position of the current instance to the next attribute
2800 * associated with the current node.
2801 *
2802 * Returns 1 in case of success, -1 in case of error, 0 if not found
2803 */
2804int
2805xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2806 if (reader == NULL)
2807 return(-1);
2808 if (reader->node == NULL)
2809 return(-1);
2810 if (reader->node->type != XML_ELEMENT_NODE)
2811 return(0);
2812 if (reader->curnode == NULL)
2813 return(xmlTextReaderMoveToFirstAttribute(reader));
2814
2815 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2816 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2817 if (ns->next != NULL) {
2818 reader->curnode = (xmlNodePtr) ns->next;
2819 return(1);
2820 }
2821 if (reader->node->properties != NULL) {
2822 reader->curnode = (xmlNodePtr) reader->node->properties;
2823 return(1);
2824 }
2825 return(0);
2826 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2827 (reader->curnode->next != NULL)) {
2828 reader->curnode = reader->curnode->next;
2829 return(1);
2830 }
2831 return(0);
2832}
2833
2834/**
2835 * xmlTextReaderMoveToElement:
2836 * @reader: the xmlTextReaderPtr used
2837 *
2838 * Moves the position of the current instance to the node that
2839 * contains the current Attribute node.
2840 *
2841 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2842 */
2843int
2844xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2845 if (reader == NULL)
2846 return(-1);
2847 if (reader->node == NULL)
2848 return(-1);
2849 if (reader->node->type != XML_ELEMENT_NODE)
2850 return(0);
2851 if (reader->curnode != NULL) {
2852 reader->curnode = NULL;
2853 return(1);
2854 }
2855 return(0);
2856}
2857
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002858/**
2859 * xmlTextReaderReadAttributeValue:
2860 * @reader: the xmlTextReaderPtr used
2861 *
2862 * Parses an attribute value into one or more Text and EntityReference nodes.
2863 *
2864 * Returns 1 in case of success, 0 if the reader was not positionned on an
2865 * ttribute node or all the attribute values have been read, or -1
2866 * in case of error.
2867 */
2868int
2869xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2870 if (reader == NULL)
2871 return(-1);
2872 if (reader->node == NULL)
2873 return(-1);
2874 if (reader->curnode == NULL)
2875 return(0);
2876 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2877 if (reader->curnode->children == NULL)
2878 return(0);
2879 reader->curnode = reader->curnode->children;
2880 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2881 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2882
2883 if (reader->faketext == NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002884 reader->faketext = xmlNewDocText(reader->node->doc,
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002885 ns->href);
2886 } else {
Daniel Veillard8874b942005-08-25 13:19:21 +00002887 if ((reader->faketext->content != NULL) &&
2888 (reader->faketext->content !=
2889 (xmlChar *) &(reader->faketext->properties)))
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002890 xmlFree(reader->faketext->content);
2891 reader->faketext->content = xmlStrdup(ns->href);
2892 }
2893 reader->curnode = reader->faketext;
2894 } else {
2895 if (reader->curnode->next == NULL)
2896 return(0);
2897 reader->curnode = reader->curnode->next;
2898 }
2899 return(1);
2900}
2901
Daniel Veillarde2811272004-10-19 09:04:23 +00002902/**
2903 * xmlTextReaderConstEncoding:
2904 * @reader: the xmlTextReaderPtr used
2905 *
2906 * Determine the encoding of the document being read.
2907 *
2908 * Returns a string containing the encoding of the document or NULL in
2909 * case of error. The string is deallocated with the reader.
2910 */
2911const xmlChar *
2912xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
2913 xmlDocPtr doc = NULL;
2914 if (reader == NULL)
2915 return(NULL);
2916 if (reader->doc != NULL)
2917 doc = reader->doc;
2918 else if (reader->ctxt != NULL)
2919 doc = reader->ctxt->myDoc;
2920 if (doc == NULL)
2921 return(NULL);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002922
Daniel Veillarde2811272004-10-19 09:04:23 +00002923 if (doc->encoding == NULL)
2924 return(NULL);
2925 else
2926 return(CONSTSTR(doc->encoding));
2927}
2928
2929
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002930/************************************************************************
2931 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002932 * Acces API to the current node *
2933 * *
2934 ************************************************************************/
2935/**
2936 * xmlTextReaderAttributeCount:
2937 * @reader: the xmlTextReaderPtr used
2938 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002939 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002940 *
2941 * Returns 0 i no attributes, -1 in case of error or the attribute count
2942 */
2943int
2944xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2945 int ret;
2946 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002947 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002948 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002949
2950 if (reader == NULL)
2951 return(-1);
2952 if (reader->node == NULL)
2953 return(0);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002954
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002955 if (reader->curnode != NULL)
2956 node = reader->curnode;
2957 else
2958 node = reader->node;
2959
2960 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002961 return(0);
2962 if ((reader->state == XML_TEXTREADER_END) ||
2963 (reader->state == XML_TEXTREADER_BACKTRACK))
2964 return(0);
2965 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002966 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002967 while (attr != NULL) {
2968 ret++;
2969 attr = attr->next;
2970 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002971 ns = node->nsDef;
2972 while (ns != NULL) {
2973 ret++;
2974 ns = ns->next;
2975 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002976 return(ret);
2977}
2978
2979/**
2980 * xmlTextReaderNodeType:
2981 * @reader: the xmlTextReaderPtr used
2982 *
2983 * Get the node type of the current node
2984 * Reference:
Daniel Veillard354cf5c2008-04-07 12:46:48 +00002985 * http://www.gnu.org/software/dotgnu/pnetlib-doc/System/Xml/XmlNodeType.html
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002986 *
2987 * Returns the xmlNodeType of the current node or -1 in case of error
2988 */
2989int
2990xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002991 xmlNodePtr node;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002992
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002993 if (reader == NULL)
2994 return(-1);
2995 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00002996 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002997 if (reader->curnode != NULL)
2998 node = reader->curnode;
2999 else
3000 node = reader->node;
3001 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003002 case XML_ELEMENT_NODE:
3003 if ((reader->state == XML_TEXTREADER_END) ||
3004 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00003005 return(XML_READER_TYPE_END_ELEMENT);
3006 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00003007 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003008 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003009 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003010 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003011 if (xmlIsBlankNode(reader->node)) {
3012 if (xmlNodeGetSpacePreserve(reader->node))
3013 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
3014 else
3015 return(XML_READER_TYPE_WHITESPACE);
3016 } else {
3017 return(XML_READER_TYPE_TEXT);
3018 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003019 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003020 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003021 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003022 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003023 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003024 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003025 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003026 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003027 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003028 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003029 case XML_DOCUMENT_NODE:
3030 case XML_HTML_DOCUMENT_NODE:
3031#ifdef LIBXML_DOCB_ENABLED
3032 case XML_DOCB_DOCUMENT_NODE:
3033#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00003034 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003035 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003036 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003037 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003038 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003039 case XML_DOCUMENT_TYPE_NODE:
3040 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003041 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003042
3043 case XML_ELEMENT_DECL:
3044 case XML_ATTRIBUTE_DECL:
3045 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003046 case XML_XINCLUDE_START:
3047 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003048 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003049 }
3050 return(-1);
3051}
3052
3053/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00003054 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003055 * @reader: the xmlTextReaderPtr used
3056 *
3057 * Check if the current node is empty
3058 *
3059 * Returns 1 if empty, 0 if not and -1 in case of error
3060 */
3061int
3062xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
3063 if ((reader == NULL) || (reader->node == NULL))
3064 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00003065 if (reader->node->type != XML_ELEMENT_NODE)
3066 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00003067 if (reader->curnode != NULL)
3068 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003069 if (reader->node->children != NULL)
3070 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00003071 if (reader->state == XML_TEXTREADER_END)
3072 return(0);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00003073 if (reader->doc != NULL)
3074 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00003075#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard7899c5c2003-11-03 12:31:38 +00003076 if (reader->in_xinclude > 0)
3077 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00003078#endif
Daniel Veillarde8039df2003-10-27 11:25:13 +00003079 return((reader->node->extra & NODE_IS_EMPTY) != 0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003080}
3081
3082/**
3083 * xmlTextReaderLocalName:
3084 * @reader: the xmlTextReaderPtr used
3085 *
3086 * The local name of the node.
3087 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003088 * Returns the local name or NULL if not available,
3089 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003090 */
3091xmlChar *
3092xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003093 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003094 if ((reader == NULL) || (reader->node == NULL))
3095 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003096 if (reader->curnode != NULL)
3097 node = reader->curnode;
3098 else
3099 node = reader->node;
3100 if (node->type == XML_NAMESPACE_DECL) {
3101 xmlNsPtr ns = (xmlNsPtr) node;
3102 if (ns->prefix == NULL)
3103 return(xmlStrdup(BAD_CAST "xmlns"));
3104 else
3105 return(xmlStrdup(ns->prefix));
3106 }
3107 if ((node->type != XML_ELEMENT_NODE) &&
3108 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003109 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003110 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003111}
3112
3113/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003114 * xmlTextReaderConstLocalName:
3115 * @reader: the xmlTextReaderPtr used
3116 *
3117 * The local name of the node.
3118 *
3119 * Returns the local name or NULL if not available, the
3120 * string will be deallocated with the reader.
3121 */
3122const xmlChar *
3123xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
3124 xmlNodePtr node;
3125 if ((reader == NULL) || (reader->node == NULL))
3126 return(NULL);
3127 if (reader->curnode != NULL)
3128 node = reader->curnode;
3129 else
3130 node = reader->node;
3131 if (node->type == XML_NAMESPACE_DECL) {
3132 xmlNsPtr ns = (xmlNsPtr) node;
3133 if (ns->prefix == NULL)
3134 return(CONSTSTR(BAD_CAST "xmlns"));
3135 else
3136 return(ns->prefix);
3137 }
3138 if ((node->type != XML_ELEMENT_NODE) &&
3139 (node->type != XML_ATTRIBUTE_NODE))
3140 return(xmlTextReaderConstName(reader));
3141 return(node->name);
3142}
3143
3144/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003145 * xmlTextReaderName:
3146 * @reader: the xmlTextReaderPtr used
3147 *
3148 * The qualified name of the node, equal to Prefix :LocalName.
3149 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003150 * Returns the local name or NULL if not available,
3151 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003152 */
3153xmlChar *
3154xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003155 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003156 xmlChar *ret;
3157
3158 if ((reader == NULL) || (reader->node == NULL))
3159 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003160 if (reader->curnode != NULL)
3161 node = reader->curnode;
3162 else
3163 node = reader->node;
3164 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003165 case XML_ELEMENT_NODE:
3166 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003167 if ((node->ns == NULL) ||
3168 (node->ns->prefix == NULL))
3169 return(xmlStrdup(node->name));
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003170
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003171 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003172 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003173 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003174 return(ret);
3175 case XML_TEXT_NODE:
3176 return(xmlStrdup(BAD_CAST "#text"));
3177 case XML_CDATA_SECTION_NODE:
3178 return(xmlStrdup(BAD_CAST "#cdata-section"));
3179 case XML_ENTITY_NODE:
3180 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003181 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003182 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003183 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003184 case XML_COMMENT_NODE:
3185 return(xmlStrdup(BAD_CAST "#comment"));
3186 case XML_DOCUMENT_NODE:
3187 case XML_HTML_DOCUMENT_NODE:
3188#ifdef LIBXML_DOCB_ENABLED
3189 case XML_DOCB_DOCUMENT_NODE:
3190#endif
3191 return(xmlStrdup(BAD_CAST "#document"));
3192 case XML_DOCUMENT_FRAG_NODE:
3193 return(xmlStrdup(BAD_CAST "#document-fragment"));
3194 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003195 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003196 case XML_DOCUMENT_TYPE_NODE:
3197 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003198 return(xmlStrdup(node->name));
3199 case XML_NAMESPACE_DECL: {
3200 xmlNsPtr ns = (xmlNsPtr) node;
3201
3202 ret = xmlStrdup(BAD_CAST "xmlns");
3203 if (ns->prefix == NULL)
3204 return(ret);
3205 ret = xmlStrcat(ret, BAD_CAST ":");
3206 ret = xmlStrcat(ret, ns->prefix);
3207 return(ret);
3208 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003209
3210 case XML_ELEMENT_DECL:
3211 case XML_ATTRIBUTE_DECL:
3212 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003213 case XML_XINCLUDE_START:
3214 case XML_XINCLUDE_END:
3215 return(NULL);
3216 }
3217 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003218}
3219
3220/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003221 * xmlTextReaderConstName:
3222 * @reader: the xmlTextReaderPtr used
3223 *
3224 * The qualified name of the node, equal to Prefix :LocalName.
3225 *
3226 * Returns the local name or NULL if not available, the string is
3227 * deallocated with the reader.
3228 */
3229const xmlChar *
3230xmlTextReaderConstName(xmlTextReaderPtr reader) {
3231 xmlNodePtr node;
3232
3233 if ((reader == NULL) || (reader->node == NULL))
3234 return(NULL);
3235 if (reader->curnode != NULL)
3236 node = reader->curnode;
3237 else
3238 node = reader->node;
3239 switch (node->type) {
3240 case XML_ELEMENT_NODE:
3241 case XML_ATTRIBUTE_NODE:
3242 if ((node->ns == NULL) ||
3243 (node->ns->prefix == NULL))
3244 return(node->name);
3245 return(CONSTQSTR(node->ns->prefix, node->name));
3246 case XML_TEXT_NODE:
3247 return(CONSTSTR(BAD_CAST "#text"));
3248 case XML_CDATA_SECTION_NODE:
3249 return(CONSTSTR(BAD_CAST "#cdata-section"));
3250 case XML_ENTITY_NODE:
3251 case XML_ENTITY_REF_NODE:
3252 return(CONSTSTR(node->name));
3253 case XML_PI_NODE:
3254 return(CONSTSTR(node->name));
3255 case XML_COMMENT_NODE:
3256 return(CONSTSTR(BAD_CAST "#comment"));
3257 case XML_DOCUMENT_NODE:
3258 case XML_HTML_DOCUMENT_NODE:
3259#ifdef LIBXML_DOCB_ENABLED
3260 case XML_DOCB_DOCUMENT_NODE:
3261#endif
3262 return(CONSTSTR(BAD_CAST "#document"));
3263 case XML_DOCUMENT_FRAG_NODE:
3264 return(CONSTSTR(BAD_CAST "#document-fragment"));
3265 case XML_NOTATION_NODE:
3266 return(CONSTSTR(node->name));
3267 case XML_DOCUMENT_TYPE_NODE:
3268 case XML_DTD_NODE:
3269 return(CONSTSTR(node->name));
3270 case XML_NAMESPACE_DECL: {
3271 xmlNsPtr ns = (xmlNsPtr) node;
3272
3273 if (ns->prefix == NULL)
3274 return(CONSTSTR(BAD_CAST "xmlns"));
3275 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
3276 }
3277
3278 case XML_ELEMENT_DECL:
3279 case XML_ATTRIBUTE_DECL:
3280 case XML_ENTITY_DECL:
3281 case XML_XINCLUDE_START:
3282 case XML_XINCLUDE_END:
3283 return(NULL);
3284 }
3285 return(NULL);
3286}
3287
3288/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003289 * xmlTextReaderPrefix:
3290 * @reader: the xmlTextReaderPtr used
3291 *
3292 * A shorthand reference to the namespace associated with the node.
3293 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003294 * Returns the prefix or NULL if not available,
3295 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003296 */
3297xmlChar *
3298xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003299 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003300 if ((reader == NULL) || (reader->node == NULL))
3301 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003302 if (reader->curnode != NULL)
3303 node = reader->curnode;
3304 else
3305 node = reader->node;
3306 if (node->type == XML_NAMESPACE_DECL) {
3307 xmlNsPtr ns = (xmlNsPtr) node;
3308 if (ns->prefix == NULL)
3309 return(NULL);
3310 return(xmlStrdup(BAD_CAST "xmlns"));
3311 }
3312 if ((node->type != XML_ELEMENT_NODE) &&
3313 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003314 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00003315 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003316 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003317 return(NULL);
3318}
3319
3320/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003321 * xmlTextReaderConstPrefix:
3322 * @reader: the xmlTextReaderPtr used
3323 *
3324 * A shorthand reference to the namespace associated with the node.
3325 *
3326 * Returns the prefix or NULL if not available, the string is deallocated
3327 * with the reader.
3328 */
3329const xmlChar *
3330xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3331 xmlNodePtr node;
3332 if ((reader == NULL) || (reader->node == NULL))
3333 return(NULL);
3334 if (reader->curnode != NULL)
3335 node = reader->curnode;
3336 else
3337 node = reader->node;
3338 if (node->type == XML_NAMESPACE_DECL) {
3339 xmlNsPtr ns = (xmlNsPtr) node;
3340 if (ns->prefix == NULL)
3341 return(NULL);
3342 return(CONSTSTR(BAD_CAST "xmlns"));
3343 }
3344 if ((node->type != XML_ELEMENT_NODE) &&
3345 (node->type != XML_ATTRIBUTE_NODE))
3346 return(NULL);
3347 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3348 return(CONSTSTR(node->ns->prefix));
3349 return(NULL);
3350}
3351
3352/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003353 * xmlTextReaderNamespaceUri:
3354 * @reader: the xmlTextReaderPtr used
3355 *
3356 * The URI defining the namespace associated with the node.
3357 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003358 * Returns the namespace URI or NULL if not available,
3359 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003360 */
3361xmlChar *
3362xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003363 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003364 if ((reader == NULL) || (reader->node == NULL))
3365 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003366 if (reader->curnode != NULL)
3367 node = reader->curnode;
3368 else
3369 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00003370 if (node->type == XML_NAMESPACE_DECL)
3371 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003372 if ((node->type != XML_ELEMENT_NODE) &&
3373 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003374 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003375 if (node->ns != NULL)
3376 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003377 return(NULL);
3378}
3379
3380/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003381 * xmlTextReaderConstNamespaceUri:
3382 * @reader: the xmlTextReaderPtr used
3383 *
3384 * The URI defining the namespace associated with the node.
3385 *
3386 * Returns the namespace URI or NULL if not available, the string
3387 * will be deallocated with the reader
3388 */
3389const xmlChar *
3390xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3391 xmlNodePtr node;
3392 if ((reader == NULL) || (reader->node == NULL))
3393 return(NULL);
3394 if (reader->curnode != NULL)
3395 node = reader->curnode;
3396 else
3397 node = reader->node;
3398 if (node->type == XML_NAMESPACE_DECL)
3399 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3400 if ((node->type != XML_ELEMENT_NODE) &&
3401 (node->type != XML_ATTRIBUTE_NODE))
3402 return(NULL);
3403 if (node->ns != NULL)
3404 return(CONSTSTR(node->ns->href));
3405 return(NULL);
3406}
3407
3408/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003409 * xmlTextReaderBaseUri:
3410 * @reader: the xmlTextReaderPtr used
3411 *
3412 * The base URI of the node.
3413 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003414 * Returns the base URI or NULL if not available,
3415 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003416 */
3417xmlChar *
3418xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3419 if ((reader == NULL) || (reader->node == NULL))
3420 return(NULL);
3421 return(xmlNodeGetBase(NULL, reader->node));
3422}
3423
3424/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003425 * xmlTextReaderConstBaseUri:
3426 * @reader: the xmlTextReaderPtr used
3427 *
3428 * The base URI of the node.
3429 *
3430 * Returns the base URI or NULL if not available, the string
3431 * will be deallocated with the reader
3432 */
3433const xmlChar *
3434xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3435 xmlChar *tmp;
3436 const xmlChar *ret;
3437
3438 if ((reader == NULL) || (reader->node == NULL))
3439 return(NULL);
3440 tmp = xmlNodeGetBase(NULL, reader->node);
3441 if (tmp == NULL)
3442 return(NULL);
3443 ret = CONSTSTR(tmp);
3444 xmlFree(tmp);
3445 return(ret);
3446}
3447
3448/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003449 * xmlTextReaderDepth:
3450 * @reader: the xmlTextReaderPtr used
3451 *
3452 * The depth of the node in the tree.
3453 *
3454 * Returns the depth or -1 in case of error
3455 */
3456int
3457xmlTextReaderDepth(xmlTextReaderPtr reader) {
3458 if (reader == NULL)
3459 return(-1);
3460 if (reader->node == NULL)
3461 return(0);
3462
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003463 if (reader->curnode != NULL) {
3464 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3465 (reader->curnode->type == XML_NAMESPACE_DECL))
3466 return(reader->depth + 1);
3467 return(reader->depth + 2);
3468 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003469 return(reader->depth);
3470}
3471
3472/**
3473 * xmlTextReaderHasAttributes:
3474 * @reader: the xmlTextReaderPtr used
3475 *
3476 * Whether the node has attributes.
3477 *
3478 * Returns 1 if true, 0 if false, and -1 in case or error
3479 */
3480int
3481xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003482 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003483 if (reader == NULL)
3484 return(-1);
3485 if (reader->node == NULL)
3486 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003487 if (reader->curnode != NULL)
3488 node = reader->curnode;
3489 else
3490 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003491
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003492 if ((node->type == XML_ELEMENT_NODE) &&
Daniel Veillard6bb3e862004-11-24 12:39:00 +00003493 ((node->properties != NULL) || (node->nsDef != NULL)))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003494 return(1);
3495 /* TODO: handle the xmlDecl */
3496 return(0);
3497}
3498
3499/**
3500 * xmlTextReaderHasValue:
3501 * @reader: the xmlTextReaderPtr used
3502 *
3503 * Whether the node can have a text value.
3504 *
3505 * Returns 1 if true, 0 if false, and -1 in case or error
3506 */
3507int
3508xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003509 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003510 if (reader == NULL)
3511 return(-1);
3512 if (reader->node == NULL)
3513 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003514 if (reader->curnode != NULL)
3515 node = reader->curnode;
3516 else
3517 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003518
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003519 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003520 case XML_ATTRIBUTE_NODE:
3521 case XML_TEXT_NODE:
3522 case XML_CDATA_SECTION_NODE:
3523 case XML_PI_NODE:
3524 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00003525 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003526 return(1);
3527 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003528 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003529 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003530 return(0);
3531}
3532
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003533/**
3534 * xmlTextReaderValue:
3535 * @reader: the xmlTextReaderPtr used
3536 *
3537 * Provides the text value of the node if present
3538 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003539 * Returns the string or NULL if not available. The result must be deallocated
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003540 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003541 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003542xmlChar *
3543xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003544 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003545 if (reader == NULL)
3546 return(NULL);
3547 if (reader->node == NULL)
3548 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003549 if (reader->curnode != NULL)
3550 node = reader->curnode;
3551 else
3552 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003553
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003554 switch (node->type) {
3555 case XML_NAMESPACE_DECL:
3556 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003557 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003558 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003559
3560 if (attr->parent != NULL)
3561 return (xmlNodeListGetString
3562 (attr->parent->doc, attr->children, 1));
3563 else
3564 return (xmlNodeListGetString(NULL, attr->children, 1));
3565 break;
3566 }
3567 case XML_TEXT_NODE:
3568 case XML_CDATA_SECTION_NODE:
3569 case XML_PI_NODE:
3570 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003571 if (node->content != NULL)
3572 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003573 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003574 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003575 }
3576 return(NULL);
3577}
3578
3579/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003580 * xmlTextReaderConstValue:
3581 * @reader: the xmlTextReaderPtr used
3582 *
3583 * Provides the text value of the node if present
3584 *
3585 * Returns the string or NULL if not available. The result will be
3586 * deallocated on the next Read() operation.
3587 */
3588const xmlChar *
3589xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3590 xmlNodePtr node;
3591 if (reader == NULL)
3592 return(NULL);
3593 if (reader->node == NULL)
3594 return(NULL);
3595 if (reader->curnode != NULL)
3596 node = reader->curnode;
3597 else
3598 node = reader->node;
3599
3600 switch (node->type) {
3601 case XML_NAMESPACE_DECL:
3602 return(((xmlNsPtr) node)->href);
3603 case XML_ATTRIBUTE_NODE:{
3604 xmlAttrPtr attr = (xmlAttrPtr) node;
3605
3606 if ((attr->children != NULL) &&
3607 (attr->children->type == XML_TEXT_NODE) &&
3608 (attr->children->next == NULL))
3609 return(attr->children->content);
3610 else {
Daniel Veillard8165a6b2004-07-01 11:20:33 +00003611 if (reader->buffer == NULL) {
Daniel Veillard8aebce32012-07-16 14:42:31 +08003612 reader->buffer = xmlBufCreateSize(100);
3613 if (reader->buffer == NULL) {
3614 xmlGenericError(xmlGenericErrorContext,
3615 "xmlTextReaderSetup : malloc failed\n");
3616 return (NULL);
3617 }
3618 } else
3619 xmlBufEmpty(reader->buffer);
3620 xmlBufGetNodeContent(reader->buffer, node);
3621 return(xmlBufContent(reader->buffer));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003622 }
3623 break;
3624 }
3625 case XML_TEXT_NODE:
3626 case XML_CDATA_SECTION_NODE:
3627 case XML_PI_NODE:
3628 case XML_COMMENT_NODE:
3629 return(node->content);
3630 default:
3631 break;
3632 }
3633 return(NULL);
3634}
3635
3636/**
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003637 * xmlTextReaderIsDefault:
3638 * @reader: the xmlTextReaderPtr used
3639 *
3640 * Whether an Attribute node was generated from the default value
3641 * defined in the DTD or schema.
3642 *
3643 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3644 */
3645int
3646xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3647 if (reader == NULL)
3648 return(-1);
3649 return(0);
3650}
3651
3652/**
3653 * xmlTextReaderQuoteChar:
3654 * @reader: the xmlTextReaderPtr used
3655 *
3656 * The quotation mark character used to enclose the value of an attribute.
3657 *
3658 * Returns " or ' and -1 in case of error
3659 */
3660int
3661xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3662 if (reader == NULL)
3663 return(-1);
3664 /* TODO maybe lookup the attribute value for " first */
3665 return((int) '"');
3666}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003667
3668/**
3669 * xmlTextReaderXmlLang:
3670 * @reader: the xmlTextReaderPtr used
3671 *
3672 * The xml:lang scope within which the node resides.
3673 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003674 * Returns the xml:lang value or NULL if none exists.,
3675 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003676 */
3677xmlChar *
3678xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3679 if (reader == NULL)
3680 return(NULL);
3681 if (reader->node == NULL)
3682 return(NULL);
3683 return(xmlNodeGetLang(reader->node));
3684}
3685
Daniel Veillard67df8092002-12-16 22:04:11 +00003686/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00003687 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00003688 * @reader: the xmlTextReaderPtr used
3689 *
3690 * The xml:lang scope within which the node resides.
3691 *
3692 * Returns the xml:lang value or NULL if none exists.
3693 */
3694const xmlChar *
3695xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3696 xmlChar *tmp;
3697 const xmlChar *ret;
3698
3699 if (reader == NULL)
3700 return(NULL);
3701 if (reader->node == NULL)
3702 return(NULL);
3703 tmp = xmlNodeGetLang(reader->node);
3704 if (tmp == NULL)
3705 return(NULL);
3706 ret = CONSTSTR(tmp);
3707 xmlFree(tmp);
3708 return(ret);
3709}
3710
3711/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00003712 * xmlTextReaderConstString:
3713 * @reader: the xmlTextReaderPtr used
3714 * @str: the string to intern.
3715 *
3716 * Get an interned string from the reader, allows for example to
3717 * speedup string name comparisons
3718 *
3719 * Returns an interned copy of the string or NULL in case of error. The
3720 * string will be deallocated with the reader.
3721 */
3722const xmlChar *
3723xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3724 if (reader == NULL)
3725 return(NULL);
3726 return(CONSTSTR(str));
3727}
3728
3729/**
Daniel Veillard67df8092002-12-16 22:04:11 +00003730 * xmlTextReaderNormalization:
3731 * @reader: the xmlTextReaderPtr used
3732 *
3733 * The value indicating whether to normalize white space and attribute values.
3734 * Since attribute value and end of line normalizations are a MUST in the XML
3735 * specification only the value true is accepted. The broken bahaviour of
3736 * accepting out of range character entities like &#0; is of course not
3737 * supported either.
3738 *
3739 * Returns 1 or -1 in case of error.
3740 */
3741int
3742xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3743 if (reader == NULL)
3744 return(-1);
3745 return(1);
3746}
3747
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003748/************************************************************************
3749 * *
3750 * Extensions to the base APIs *
3751 * *
3752 ************************************************************************/
3753
3754/**
3755 * xmlTextReaderSetParserProp:
3756 * @reader: the xmlTextReaderPtr used
3757 * @prop: the xmlParserProperties to set
3758 * @value: usually 0 or 1 to (de)activate it
3759 *
3760 * Change the parser processing behaviour by changing some of its internal
3761 * properties. Note that some properties can only be changed before any
3762 * read has been done.
3763 *
3764 * Returns 0 if the call was successful, or -1 in case of error
3765 */
3766int
3767xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3768 xmlParserProperties p = (xmlParserProperties) prop;
3769 xmlParserCtxtPtr ctxt;
3770
3771 if ((reader == NULL) || (reader->ctxt == NULL))
3772 return(-1);
3773 ctxt = reader->ctxt;
3774
3775 switch (p) {
3776 case XML_PARSER_LOADDTD:
3777 if (value != 0) {
3778 if (ctxt->loadsubset == 0) {
3779 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3780 return(-1);
3781 ctxt->loadsubset = XML_DETECT_IDS;
3782 }
3783 } else {
3784 ctxt->loadsubset = 0;
3785 }
3786 return(0);
3787 case XML_PARSER_DEFAULTATTRS:
3788 if (value != 0) {
3789 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3790 } else {
3791 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3792 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3793 }
3794 return(0);
3795 case XML_PARSER_VALIDATE:
3796 if (value != 0) {
3797 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003798 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003799 } else {
3800 ctxt->validate = 0;
3801 }
3802 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003803 case XML_PARSER_SUBST_ENTITIES:
3804 if (value != 0) {
3805 ctxt->replaceEntities = 1;
3806 } else {
3807 ctxt->replaceEntities = 0;
3808 }
3809 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003810 }
3811 return(-1);
3812}
3813
3814/**
3815 * xmlTextReaderGetParserProp:
3816 * @reader: the xmlTextReaderPtr used
3817 * @prop: the xmlParserProperties to get
3818 *
3819 * Read the parser internal property.
3820 *
3821 * Returns the value, usually 0 or 1, or -1 in case of error.
3822 */
3823int
3824xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3825 xmlParserProperties p = (xmlParserProperties) prop;
3826 xmlParserCtxtPtr ctxt;
3827
3828 if ((reader == NULL) || (reader->ctxt == NULL))
3829 return(-1);
3830 ctxt = reader->ctxt;
3831
3832 switch (p) {
3833 case XML_PARSER_LOADDTD:
3834 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3835 return(1);
3836 return(0);
3837 case XML_PARSER_DEFAULTATTRS:
3838 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3839 return(1);
3840 return(0);
3841 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003842 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003843 case XML_PARSER_SUBST_ENTITIES:
3844 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003845 }
3846 return(-1);
3847}
3848
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003849
Daniel Veillarde18fc182002-12-28 22:56:33 +00003850/**
Aleksey Sanind671e282005-01-03 21:58:59 +00003851 * xmlTextReaderGetParserLineNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003852 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003853 *
3854 * Provide the line number of the current parsing point.
3855 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003856 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003857 */
3858int
3859xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
3860{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003861 if ((reader == NULL) || (reader->ctxt == NULL) ||
3862 (reader->ctxt->input == NULL)) {
3863 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003864 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003865 return (reader->ctxt->input->line);
Aleksey Sanind671e282005-01-03 21:58:59 +00003866}
3867
3868/**
3869 * xmlTextReaderGetParserColumnNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003870 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003871 *
3872 * Provide the column number of the current parsing point.
3873 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003874 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003875 */
3876int
3877xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
3878{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003879 if ((reader == NULL) || (reader->ctxt == NULL) ||
3880 (reader->ctxt->input == NULL)) {
3881 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003882 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003883 return (reader->ctxt->input->col);
Aleksey Sanind671e282005-01-03 21:58:59 +00003884}
3885
3886/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003887 * xmlTextReaderCurrentNode:
3888 * @reader: the xmlTextReaderPtr used
3889 *
3890 * Hacking interface allowing to get the xmlNodePtr correponding to the
3891 * current node being accessed by the xmlTextReader. This is dangerous
3892 * because the underlying node may be destroyed on the next Reads.
3893 *
3894 * Returns the xmlNodePtr or NULL in case of error.
3895 */
3896xmlNodePtr
3897xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3898 if (reader == NULL)
3899 return(NULL);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003900
Daniel Veillarde18fc182002-12-28 22:56:33 +00003901 if (reader->curnode != NULL)
3902 return(reader->curnode);
3903 return(reader->node);
3904}
3905
3906/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003907 * xmlTextReaderPreserve:
3908 * @reader: the xmlTextReaderPtr used
3909 *
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003910 * This tells the XML Reader to preserve the current node.
3911 * The caller must also use xmlTextReaderCurrentDoc() to
3912 * keep an handle on the resulting document once parsing has finished
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003913 *
3914 * Returns the xmlNodePtr or NULL in case of error.
3915 */
3916xmlNodePtr
3917xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3918 xmlNodePtr cur, parent;
3919
3920 if (reader == NULL)
3921 return(NULL);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003922
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003923 if (reader->curnode != NULL)
3924 cur = reader->curnode;
3925 else
3926 cur = reader->node;
3927 if (cur == NULL)
3928 return(NULL);
Daniel Veillard1e906612003-12-05 14:57:46 +00003929
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003930 if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003931 cur->extra |= NODE_IS_PRESERVED;
3932 cur->extra |= NODE_IS_SPRESERVED;
3933 }
3934 reader->preserves++;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003935
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003936 parent = cur->parent;;
3937 while (parent != NULL) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003938 if (parent->type == XML_ELEMENT_NODE)
3939 parent->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003940 parent = parent->parent;
3941 }
3942 return(cur);
3943}
3944
Daniel Veillard1e906612003-12-05 14:57:46 +00003945#ifdef LIBXML_PATTERN_ENABLED
3946/**
3947 * xmlTextReaderPreservePattern:
3948 * @reader: the xmlTextReaderPtr used
3949 * @pattern: an XPath subset pattern
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003950 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003951 *
Daniel Veillard1e906612003-12-05 14:57:46 +00003952 * This tells the XML Reader to preserve all nodes matched by the
3953 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3954 * keep an handle on the resulting document once parsing has finished
3955 *
3956 * Returns a positive number in case of success and -1 in case of error
3957 */
3958int
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003959xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3960 const xmlChar **namespaces)
3961{
Daniel Veillard1e906612003-12-05 14:57:46 +00003962 xmlPatternPtr comp;
3963
3964 if ((reader == NULL) || (pattern == NULL))
3965 return(-1);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003966
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003967 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
Daniel Veillard1e906612003-12-05 14:57:46 +00003968 if (comp == NULL)
3969 return(-1);
3970
3971 if (reader->patternMax <= 0) {
3972 reader->patternMax = 4;
3973 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3974 sizeof(reader->patternTab[0]));
3975 if (reader->patternTab == NULL) {
3976 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3977 return (-1);
3978 }
3979 }
3980 if (reader->patternNr >= reader->patternMax) {
3981 xmlPatternPtr *tmp;
3982 reader->patternMax *= 2;
3983 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3984 reader->patternMax *
3985 sizeof(reader->patternTab[0]));
3986 if (tmp == NULL) {
3987 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3988 reader->patternMax /= 2;
3989 return (-1);
3990 }
3991 reader->patternTab = tmp;
3992 }
3993 reader->patternTab[reader->patternNr] = comp;
3994 return(reader->patternNr++);
3995}
3996#endif
3997
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003998/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003999 * xmlTextReaderCurrentDoc:
4000 * @reader: the xmlTextReaderPtr used
4001 *
4002 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004003 * current document being accessed by the xmlTextReader.
Daniel Veillard9ee35f32003-09-28 00:19:54 +00004004 * NOTE: as a result of this call, the reader will not destroy the
4005 * associated XML document and calling xmlFreeDoc() on the result
4006 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00004007 *
4008 * Returns the xmlDocPtr or NULL in case of error.
4009 */
4010xmlDocPtr
4011xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004012 if (reader == NULL)
4013 return(NULL);
4014 if (reader->doc != NULL)
4015 return(reader->doc);
Daniel Veillard14dad702008-03-14 14:29:40 +00004016 if ((reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00004017 return(NULL);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004018
Daniel Veillard9ee35f32003-09-28 00:19:54 +00004019 reader->preserve = 1;
Daniel Veillarde18fc182002-12-28 22:56:33 +00004020 return(reader->ctxt->myDoc);
4021}
4022
Daniel Veillard37fc84d2003-05-09 19:38:15 +00004023#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004024static char *xmlTextReaderBuildMessage(const char *msg, va_list ap);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004025
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004026static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004027xmlTextReaderValidityError(void *ctxt, const char *msg, ...);
4028
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004029static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004030xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...);
4031
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004032static void XMLCDECL
4033xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004034{
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004035 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004036
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004037 char *str;
4038
4039 va_list ap;
4040
4041 va_start(ap, msg);
4042 str = xmlTextReaderBuildMessage(msg, ap);
4043 if (!reader->errorFunc) {
4044 xmlTextReaderValidityError(ctx, "%s", str);
4045 } else {
4046 reader->errorFunc(reader->errorFuncArg, str,
4047 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4048 NULL /* locator */ );
4049 }
4050 if (str != NULL)
4051 xmlFree(str);
4052 va_end(ap);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004053}
4054
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004055static void XMLCDECL
4056xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004057{
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004058 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004059
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004060 char *str;
4061
4062 va_list ap;
4063
4064 va_start(ap, msg);
4065 str = xmlTextReaderBuildMessage(msg, ap);
4066 if (!reader->errorFunc) {
4067 xmlTextReaderValidityWarning(ctx, "%s", str);
4068 } else {
4069 reader->errorFunc(reader->errorFuncArg, str,
4070 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4071 NULL /* locator */ );
4072 }
4073 if (str != NULL)
4074 xmlFree(str);
4075 va_end(ap);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004076}
4077
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004078static void
4079 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004080
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004081static void
4082xmlTextReaderValidityStructuredRelay(void *userData, xmlErrorPtr error)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004083{
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004084 xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004085
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004086 if (reader->sErrorFunc) {
4087 reader->sErrorFunc(reader->errorFuncArg, error);
4088 } else {
4089 xmlTextReaderStructuredError(reader, error);
4090 }
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004091}
Daniel Veillardf4e55762003-04-15 23:32:22 +00004092/**
Daniel Veillard33300b42003-04-17 09:09:19 +00004093 * xmlTextReaderRelaxNGSetSchema:
4094 * @reader: the xmlTextReaderPtr used
4095 * @schema: a precompiled RelaxNG schema
4096 *
4097 * Use RelaxNG to validate the document as it is processed.
4098 * Activation is only possible before the first Read().
4099 * if @schema is NULL, then RelaxNG validation is desactivated.
4100 @ The @schema should not be freed until the reader is deallocated
4101 * or its use has been deactivated.
4102 *
4103 * Returns 0 in case the RelaxNG validation could be (des)activated and
4104 * -1 in case of error.
4105 */
4106int
4107xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
Daniel Veillardce682bc2004-11-05 17:22:25 +00004108 if (reader == NULL)
4109 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00004110 if (schema == NULL) {
4111 if (reader->rngSchemas != NULL) {
4112 xmlRelaxNGFree(reader->rngSchemas);
4113 reader->rngSchemas = NULL;
4114 }
4115 if (reader->rngValidCtxt != NULL) {
Noam Postavsky15794992012-03-19 16:08:16 +08004116 if (! reader->rngPreserveCtxt)
4117 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
Daniel Veillard33300b42003-04-17 09:09:19 +00004118 reader->rngValidCtxt = NULL;
4119 }
Noam Postavsky15794992012-03-19 16:08:16 +08004120 reader->rngPreserveCtxt = 0;
Daniel Veillard33300b42003-04-17 09:09:19 +00004121 return(0);
4122 }
4123 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4124 return(-1);
4125 if (reader->rngSchemas != NULL) {
4126 xmlRelaxNGFree(reader->rngSchemas);
4127 reader->rngSchemas = NULL;
4128 }
4129 if (reader->rngValidCtxt != NULL) {
Noam Postavsky15794992012-03-19 16:08:16 +08004130 if (! reader->rngPreserveCtxt)
4131 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
Daniel Veillard33300b42003-04-17 09:09:19 +00004132 reader->rngValidCtxt = NULL;
4133 }
Noam Postavsky15794992012-03-19 16:08:16 +08004134 reader->rngPreserveCtxt = 0;
Daniel Veillard33300b42003-04-17 09:09:19 +00004135 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
4136 if (reader->rngValidCtxt == NULL)
4137 return(-1);
4138 if (reader->errorFunc != NULL) {
4139 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004140 xmlTextReaderValidityErrorRelay,
4141 xmlTextReaderValidityWarningRelay,
4142 reader);
4143 }
4144 if (reader->sErrorFunc != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004145 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004146 xmlTextReaderValidityStructuredRelay,
4147 reader);
Daniel Veillard33300b42003-04-17 09:09:19 +00004148 }
4149 reader->rngValidErrors = 0;
4150 reader->rngFullNode = NULL;
4151 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4152 return(0);
4153}
4154
4155/**
Daniel Veillard97fa5b32012-08-14 11:01:07 +08004156 * xmlTextReaderLocator:
4157 * @ctx: the xmlTextReaderPtr used
4158 * @file: returned file information
4159 * @line: returned line information
4160 *
4161 * Internal locator function for the readers
4162 *
4163 * Returns 0 in case the Schema validation could be (des)activated and
4164 * -1 in case of error.
4165 */
4166static int
4167xmlTextReaderLocator(void *ctx, const char **file, unsigned long *line) {
4168 xmlTextReaderPtr reader;
4169
4170 if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
4171 return(-1);
4172
4173 if (file != NULL)
4174 *file = NULL;
4175 if (line != NULL)
4176 *line = 0;
4177
4178 reader = (xmlTextReaderPtr) ctx;
4179 if ((reader->ctxt != NULL) && (reader->ctxt->input != NULL)) {
4180 if (file != NULL)
4181 *file = reader->ctxt->input->filename;
4182 if (line != NULL)
4183 *line = reader->ctxt->input->line;
4184 return(0);
4185 }
4186 if (reader->node != NULL) {
4187 long res;
4188 int ret = 0;
4189
4190 if (line != NULL) {
4191 res = xmlGetLineNo(reader->node);
4192 if (res > 0)
4193 *line = (unsigned long) res;
4194 else
4195 ret = -1;
4196 }
4197 if (file != NULL) {
4198 xmlDocPtr doc = reader->node->doc;
4199 if ((doc != NULL) && (doc->URL != NULL))
4200 *file = (const char *) doc->URL;
4201 else
4202 ret = -1;
4203 }
4204 return(ret);
4205 }
4206 return(-1);
4207}
4208
4209/**
Daniel Veillardf10ae122005-07-10 19:03:16 +00004210 * xmlTextReaderSetSchema:
4211 * @reader: the xmlTextReaderPtr used
4212 * @schema: a precompiled Schema schema
4213 *
4214 * Use XSD Schema to validate the document as it is processed.
4215 * Activation is only possible before the first Read().
4216 * if @schema is NULL, then Schema validation is desactivated.
4217 @ The @schema should not be freed until the reader is deallocated
4218 * or its use has been deactivated.
4219 *
4220 * Returns 0 in case the Schema validation could be (des)activated and
4221 * -1 in case of error.
4222 */
4223int
4224xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
4225 if (reader == NULL)
4226 return(-1);
4227 if (schema == NULL) {
4228 if (reader->xsdPlug != NULL) {
4229 xmlSchemaSAXUnplug(reader->xsdPlug);
4230 reader->xsdPlug = NULL;
4231 }
4232 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004233 if (! reader->xsdPreserveCtxt)
4234 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004235 reader->xsdValidCtxt = NULL;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004236 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004237 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004238 if (reader->xsdSchemas != NULL) {
4239 xmlSchemaFree(reader->xsdSchemas);
4240 reader->xsdSchemas = NULL;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004241 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004242 return(0);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004243 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004244 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4245 return(-1);
4246 if (reader->xsdPlug != NULL) {
4247 xmlSchemaSAXUnplug(reader->xsdPlug);
4248 reader->xsdPlug = NULL;
4249 }
4250 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004251 if (! reader->xsdPreserveCtxt)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004252 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004253 reader->xsdValidCtxt = NULL;
4254 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004255 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004256 if (reader->xsdSchemas != NULL) {
4257 xmlSchemaFree(reader->xsdSchemas);
4258 reader->xsdSchemas = NULL;
4259 }
4260 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
4261 if (reader->xsdValidCtxt == NULL) {
4262 xmlSchemaFree(reader->xsdSchemas);
4263 reader->xsdSchemas = NULL;
4264 return(-1);
4265 }
4266 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4267 &(reader->ctxt->sax),
4268 &(reader->ctxt->userData));
4269 if (reader->xsdPlug == NULL) {
4270 xmlSchemaFree(reader->xsdSchemas);
4271 reader->xsdSchemas = NULL;
4272 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4273 reader->xsdValidCtxt = NULL;
4274 return(-1);
4275 }
Daniel Veillard97fa5b32012-08-14 11:01:07 +08004276 xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4277 xmlTextReaderLocator,
4278 (void *) reader);
4279
Daniel Veillardf10ae122005-07-10 19:03:16 +00004280 if (reader->errorFunc != NULL) {
4281 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004282 xmlTextReaderValidityErrorRelay,
4283 xmlTextReaderValidityWarningRelay,
4284 reader);
4285 }
4286 if (reader->sErrorFunc != NULL) {
4287 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4288 xmlTextReaderValidityStructuredRelay,
4289 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004290 }
4291 reader->xsdValidErrors = 0;
4292 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4293 return(0);
4294}
4295
4296/**
Noam Postavsky15794992012-03-19 16:08:16 +08004297 * xmlTextReaderRelaxNGValidateInternal:
Daniel Veillardf4e55762003-04-15 23:32:22 +00004298 * @reader: the xmlTextReaderPtr used
4299 * @rng: the path to a RelaxNG schema or NULL
Noam Postavsky15794992012-03-19 16:08:16 +08004300 * @ctxt: the RelaxNG schema validation context or NULL
4301 * @options: options (not yet used)
Daniel Veillardf4e55762003-04-15 23:32:22 +00004302 *
4303 * Use RelaxNG to validate the document as it is processed.
4304 * Activation is only possible before the first Read().
Noam Postavsky15794992012-03-19 16:08:16 +08004305 * If both @rng and @ctxt are NULL, then RelaxNG validation is deactivated.
Daniel Veillardf4e55762003-04-15 23:32:22 +00004306 *
William M. Brackd46c1ca2007-02-08 23:34:34 +00004307 * Returns 0 in case the RelaxNG validation could be (de)activated and
Noam Postavsky15794992012-03-19 16:08:16 +08004308 * -1 in case of error.
Daniel Veillardf4e55762003-04-15 23:32:22 +00004309 */
Noam Postavsky15794992012-03-19 16:08:16 +08004310static int
4311xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader,
4312 const char *rng,
4313 xmlRelaxNGValidCtxtPtr ctxt,
4314 int options ATTRIBUTE_UNUSED)
4315{
Daniel Veillardf4e55762003-04-15 23:32:22 +00004316 if (reader == NULL)
Daniel Veillardf4e55762003-04-15 23:32:22 +00004317 return(-1);
Noam Postavsky15794992012-03-19 16:08:16 +08004318
4319 if ((rng != NULL) && (ctxt != NULL))
4320 return (-1);
4321
4322 if (((rng != NULL) || (ctxt != NULL)) &&
4323 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4324 (reader->ctxt == NULL)))
4325 return(-1);
4326
4327 /* Cleanup previous validation stuff. */
4328 if (reader->rngValidCtxt != NULL) {
4329 if ( !reader->rngPreserveCtxt)
4330 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4331 reader->rngValidCtxt = NULL;
4332 }
4333 reader->rngPreserveCtxt = 0;
Daniel Veillard33300b42003-04-17 09:09:19 +00004334 if (reader->rngSchemas != NULL) {
4335 xmlRelaxNGFree(reader->rngSchemas);
4336 reader->rngSchemas = NULL;
4337 }
Noam Postavsky15794992012-03-19 16:08:16 +08004338
4339 if ((rng == NULL) && (ctxt == NULL)) {
4340 /* We just want to deactivate the validation, so get out. */
4341 return(0);
Daniel Veillard33300b42003-04-17 09:09:19 +00004342 }
Noam Postavsky15794992012-03-19 16:08:16 +08004343
4344
4345 if (rng != NULL) {
4346 xmlRelaxNGParserCtxtPtr pctxt;
4347 /* Parse the schema and create validation environment. */
4348
4349 pctxt = xmlRelaxNGNewParserCtxt(rng);
4350 if (reader->errorFunc != NULL) {
4351 xmlRelaxNGSetParserErrors(pctxt,
4352 xmlTextReaderValidityErrorRelay,
4353 xmlTextReaderValidityWarningRelay,
4354 reader);
4355 }
4356 if (reader->sErrorFunc != NULL) {
4357 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4358 xmlTextReaderValidityStructuredRelay,
4359 reader);
4360 }
4361 reader->rngSchemas = xmlRelaxNGParse(pctxt);
4362 xmlRelaxNGFreeParserCtxt(pctxt);
4363 if (reader->rngSchemas == NULL)
4364 return(-1);
4365 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
4366 if (reader->rngValidCtxt == NULL) {
4367 xmlRelaxNGFree(reader->rngSchemas);
4368 reader->rngSchemas = NULL;
4369 return(-1);
4370 }
4371 } else {
4372 /* Use the given validation context. */
4373 reader->rngValidCtxt = ctxt;
4374 reader->rngPreserveCtxt = 1;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004375 }
Noam Postavsky15794992012-03-19 16:08:16 +08004376 /*
4377 * Redirect the validation context's error channels to use
4378 * the reader channels.
4379 * TODO: In case the user provides the validation context we
4380 * could make this redirection optional.
4381 */
Daniel Veillardf4e55762003-04-15 23:32:22 +00004382 if (reader->errorFunc != NULL) {
4383 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004384 xmlTextReaderValidityErrorRelay,
4385 xmlTextReaderValidityWarningRelay,
4386 reader);
4387 }
4388 if (reader->sErrorFunc != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004389 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004390 xmlTextReaderValidityStructuredRelay,
4391 reader);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004392 }
4393 reader->rngValidErrors = 0;
4394 reader->rngFullNode = NULL;
4395 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4396 return(0);
4397}
Daniel Veillardf10ae122005-07-10 19:03:16 +00004398
4399/**
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004400 * xmlTextReaderSchemaValidateInternal:
Daniel Veillardf10ae122005-07-10 19:03:16 +00004401 * @reader: the xmlTextReaderPtr used
4402 * @xsd: the path to a W3C XSD schema or NULL
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004403 * @ctxt: the XML Schema validation context or NULL
4404 * @options: options (not used yet)
Daniel Veillardf10ae122005-07-10 19:03:16 +00004405 *
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004406 * Validate the document as it is processed using XML Schema.
Daniel Veillardf10ae122005-07-10 19:03:16 +00004407 * Activation is only possible before the first Read().
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004408 * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated.
Daniel Veillardf10ae122005-07-10 19:03:16 +00004409 *
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004410 * Returns 0 in case the schemas validation could be (de)activated and
Daniel Veillardf10ae122005-07-10 19:03:16 +00004411 * -1 in case of error.
4412 */
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004413static int
4414xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
4415 const char *xsd,
4416 xmlSchemaValidCtxtPtr ctxt,
4417 int options ATTRIBUTE_UNUSED)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004418{
Daniel Veillardf10ae122005-07-10 19:03:16 +00004419 if (reader == NULL)
4420 return(-1);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004421
4422 if ((xsd != NULL) && (ctxt != NULL))
Daniel Veillardf10ae122005-07-10 19:03:16 +00004423 return(-1);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004424
4425 if (((xsd != NULL) || (ctxt != NULL)) &&
4426 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4427 (reader->ctxt == NULL)))
4428 return(-1);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004429
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004430 /* Cleanup previous validation stuff. */
Daniel Veillardf10ae122005-07-10 19:03:16 +00004431 if (reader->xsdPlug != NULL) {
4432 xmlSchemaSAXUnplug(reader->xsdPlug);
4433 reader->xsdPlug = NULL;
4434 }
4435 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004436 if (! reader->xsdPreserveCtxt)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004437 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004438 reader->xsdValidCtxt = NULL;
4439 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004440 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004441 if (reader->xsdSchemas != NULL) {
4442 xmlSchemaFree(reader->xsdSchemas);
4443 reader->xsdSchemas = NULL;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004444 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004445
4446 if ((xsd == NULL) && (ctxt == NULL)) {
4447 /* We just want to deactivate the validation, so get out. */
4448 return(0);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004449 }
4450
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004451 if (xsd != NULL) {
4452 xmlSchemaParserCtxtPtr pctxt;
4453 /* Parse the schema and create validation environment. */
4454 pctxt = xmlSchemaNewParserCtxt(xsd);
4455 if (reader->errorFunc != NULL) {
4456 xmlSchemaSetParserErrors(pctxt,
4457 xmlTextReaderValidityErrorRelay,
4458 xmlTextReaderValidityWarningRelay,
4459 reader);
4460 }
4461 reader->xsdSchemas = xmlSchemaParse(pctxt);
4462 xmlSchemaFreeParserCtxt(pctxt);
4463 if (reader->xsdSchemas == NULL)
4464 return(-1);
4465 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4466 if (reader->xsdValidCtxt == NULL) {
4467 xmlSchemaFree(reader->xsdSchemas);
4468 reader->xsdSchemas = NULL;
4469 return(-1);
4470 }
4471 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4472 &(reader->ctxt->sax),
4473 &(reader->ctxt->userData));
4474 if (reader->xsdPlug == NULL) {
4475 xmlSchemaFree(reader->xsdSchemas);
4476 reader->xsdSchemas = NULL;
4477 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4478 reader->xsdValidCtxt = NULL;
4479 return(-1);
4480 }
4481 } else {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004482 /* Use the given validation context. */
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004483 reader->xsdValidCtxt = ctxt;
4484 reader->xsdPreserveCtxt = 1;
4485 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4486 &(reader->ctxt->sax),
4487 &(reader->ctxt->userData));
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004488 if (reader->xsdPlug == NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004489 reader->xsdValidCtxt = NULL;
4490 reader->xsdPreserveCtxt = 0;
4491 return(-1);
4492 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004493 }
Daniel Veillard97fa5b32012-08-14 11:01:07 +08004494 xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4495 xmlTextReaderLocator,
4496 (void *) reader);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004497 /*
4498 * Redirect the validation context's error channels to use
4499 * the reader channels.
4500 * TODO: In case the user provides the validation context we
4501 * could make this redirection optional.
4502 */
Daniel Veillardf10ae122005-07-10 19:03:16 +00004503 if (reader->errorFunc != NULL) {
4504 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004505 xmlTextReaderValidityErrorRelay,
4506 xmlTextReaderValidityWarningRelay,
4507 reader);
4508 }
4509 if (reader->sErrorFunc != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004510 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004511 xmlTextReaderValidityStructuredRelay,
4512 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004513 }
4514 reader->xsdValidErrors = 0;
4515 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4516 return(0);
4517}
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004518
4519/**
4520 * xmlTextReaderSchemaValidateCtxt:
4521 * @reader: the xmlTextReaderPtr used
4522 * @ctxt: the XML Schema validation context or NULL
4523 * @options: options (not used yet)
4524 *
4525 * Use W3C XSD schema context to validate the document as it is processed.
4526 * Activation is only possible before the first Read().
4527 * If @ctxt is NULL, then XML Schema validation is deactivated.
4528 *
4529 * Returns 0 in case the schemas validation could be (de)activated and
4530 * -1 in case of error.
4531 */
4532int
4533xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,
4534 xmlSchemaValidCtxtPtr ctxt,
4535 int options)
4536{
4537 return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options));
4538}
4539
4540/**
4541 * xmlTextReaderSchemaValidate:
4542 * @reader: the xmlTextReaderPtr used
4543 * @xsd: the path to a W3C XSD schema or NULL
4544 *
4545 * Use W3C XSD schema to validate the document as it is processed.
4546 * Activation is only possible before the first Read().
4547 * If @xsd is NULL, then XML Schema validation is deactivated.
4548 *
4549 * Returns 0 in case the schemas validation could be (de)activated and
4550 * -1 in case of error.
4551 */
4552int
4553xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd)
4554{
4555 return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));
4556}
Noam Postavsky15794992012-03-19 16:08:16 +08004557
4558/**
4559 * xmlTextReaderRelaxNGValidateCtxt:
4560 * @reader: the xmlTextReaderPtr used
4561 * @ctxt: the RelaxNG schema validation context or NULL
4562 * @options: options (not used yet)
4563 *
4564 * Use RelaxNG schema context to validate the document as it is processed.
4565 * Activation is only possible before the first Read().
4566 * If @ctxt is NULL, then RelaxNG schema validation is deactivated.
4567 *
4568 * Returns 0 in case the schemas validation could be (de)activated and
4569 * -1 in case of error.
4570 */
4571int
4572xmlTextReaderRelaxNGValidateCtxt(xmlTextReaderPtr reader,
4573 xmlRelaxNGValidCtxtPtr ctxt,
4574 int options)
4575{
4576 return(xmlTextReaderRelaxNGValidateInternal(reader, NULL, ctxt, options));
4577}
4578
4579/**
4580 * xmlTextReaderRelaxNGValidate:
4581 * @reader: the xmlTextReaderPtr used
4582 * @rng: the path to a RelaxNG schema or NULL
4583 *
4584 * Use RelaxNG schema to validate the document as it is processed.
4585 * Activation is only possible before the first Read().
4586 * If @rng is NULL, then RelaxNG schema validation is deactivated.
4587 *
4588 * Returns 0 in case the schemas validation could be (de)activated and
4589 * -1 in case of error.
4590 */
4591int
4592xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng)
4593{
4594 return(xmlTextReaderRelaxNGValidateInternal(reader, rng, NULL, 0));
4595}
4596
Daniel Veillard37fc84d2003-05-09 19:38:15 +00004597#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00004598
Daniel Veillarde2811272004-10-19 09:04:23 +00004599/**
4600 * xmlTextReaderIsNamespaceDecl:
4601 * @reader: the xmlTextReaderPtr used
4602 *
4603 * Determine whether the current node is a namespace declaration
4604 * rather than a regular attribute.
4605 *
4606 * Returns 1 if the current node is a namespace declaration, 0 if it
4607 * is a regular attribute or other type of node, or -1 in case of
4608 * error.
4609 */
4610int
4611xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4612 xmlNodePtr node;
4613 if (reader == NULL)
4614 return(-1);
4615 if (reader->node == NULL)
4616 return(-1);
4617 if (reader->curnode != NULL)
4618 node = reader->curnode;
4619 else
4620 node = reader->node;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004621
Daniel Veillarde2811272004-10-19 09:04:23 +00004622 if (XML_NAMESPACE_DECL == node->type)
4623 return(1);
4624 else
4625 return(0);
4626}
4627
4628/**
4629 * xmlTextReaderConstXmlVersion:
4630 * @reader: the xmlTextReaderPtr used
4631 *
4632 * Determine the XML version of the document being read.
4633 *
4634 * Returns a string containing the XML version of the document or NULL
4635 * in case of error. The string is deallocated with the reader.
4636 */
4637const xmlChar *
4638xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4639 xmlDocPtr doc = NULL;
4640 if (reader == NULL)
4641 return(NULL);
4642 if (reader->doc != NULL)
4643 doc = reader->doc;
4644 else if (reader->ctxt != NULL)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004645 doc = reader->ctxt->myDoc;
Daniel Veillarde2811272004-10-19 09:04:23 +00004646 if (doc == NULL)
4647 return(NULL);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004648
Daniel Veillarde2811272004-10-19 09:04:23 +00004649 if (doc->version == NULL)
4650 return(NULL);
4651 else
4652 return(CONSTSTR(doc->version));
4653}
4654
4655/**
4656 * xmlTextReaderStandalone:
4657 * @reader: the xmlTextReaderPtr used
4658 *
4659 * Determine the standalone status of the document being read.
4660 *
4661 * Returns 1 if the document was declared to be standalone, 0 if it
4662 * was declared to be not standalone, or -1 if the document did not
4663 * specify its standalone status or in case of error.
4664 */
4665int
4666xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4667 xmlDocPtr doc = NULL;
4668 if (reader == NULL)
4669 return(-1);
4670 if (reader->doc != NULL)
4671 doc = reader->doc;
4672 else if (reader->ctxt != NULL)
4673 doc = reader->ctxt->myDoc;
4674 if (doc == NULL)
4675 return(-1);
4676
4677 return(doc->standalone);
4678}
4679
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004680/************************************************************************
4681 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00004682 * Error Handling Extensions *
4683 * *
4684 ************************************************************************/
4685
4686/* helper to build a xmlMalloc'ed string from a format and va_list */
4687static char *
4688xmlTextReaderBuildMessage(const char *msg, va_list ap) {
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004689 int size = 0;
Daniel Veillard26f70262003-01-16 22:45:08 +00004690 int chars;
4691 char *larger;
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004692 char *str = NULL;
4693 va_list aq;
Daniel Veillard26f70262003-01-16 22:45:08 +00004694
4695 while (1) {
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004696 VA_COPY(aq, ap);
4697 chars = vsnprintf(str, size, msg, aq);
4698 va_end(aq);
4699 if (chars < 0) {
4700 xmlGenericError(xmlGenericErrorContext, "vsnprintf failed !\n");
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004701 if (str)
4702 xmlFree(str);
4703 return NULL;
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004704 }
4705 if ((chars < size) || (size == MAX_ERR_MSG_SIZE))
Daniel Veillard26f70262003-01-16 22:45:08 +00004706 break;
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004707 if (chars < MAX_ERR_MSG_SIZE)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004708 size = chars + 1;
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004709 else
4710 size = MAX_ERR_MSG_SIZE;
Daniel Veillard26f70262003-01-16 22:45:08 +00004711 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4712 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004713 if (str)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004714 xmlFree(str);
Daniel Veillard26f70262003-01-16 22:45:08 +00004715 return NULL;
4716 }
4717 str = larger;
4718 }
4719
4720 return str;
4721}
4722
Daniel Veillard417be3a2003-01-20 21:26:34 +00004723/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004724 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004725 * @locator: the xmlTextReaderLocatorPtr used
4726 *
4727 * Obtain the line number for the given locator.
4728 *
4729 * Returns the line number or -1 in case of error.
4730 */
4731int
4732xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4733 /* we know that locator is a xmlParserCtxtPtr */
4734 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4735 int ret = -1;
4736
Daniel Veillardce682bc2004-11-05 17:22:25 +00004737 if (locator == NULL)
4738 return(-1);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004739 if (ctx->node != NULL) {
4740 ret = xmlGetLineNo(ctx->node);
4741 }
4742 else {
4743 /* inspired from error.c */
4744 xmlParserInputPtr input;
4745 input = ctx->input;
4746 if ((input->filename == NULL) && (ctx->inputNr > 1))
4747 input = ctx->inputTab[ctx->inputNr - 2];
4748 if (input != NULL) {
4749 ret = input->line;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004750 }
Daniel Veillard417be3a2003-01-20 21:26:34 +00004751 else {
4752 ret = -1;
4753 }
4754 }
4755
4756 return ret;
4757}
4758
4759/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004760 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004761 * @locator: the xmlTextReaderLocatorPtr used
4762 *
4763 * Obtain the base URI for the given locator.
4764 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004765 * Returns the base URI or NULL in case of error,
4766 * if non NULL it need to be freed by the caller.
Daniel Veillard417be3a2003-01-20 21:26:34 +00004767 */
4768xmlChar *
4769xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4770 /* we know that locator is a xmlParserCtxtPtr */
4771 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4772 xmlChar *ret = NULL;
4773
Daniel Veillardce682bc2004-11-05 17:22:25 +00004774 if (locator == NULL)
4775 return(NULL);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004776 if (ctx->node != NULL) {
4777 ret = xmlNodeGetBase(NULL,ctx->node);
4778 }
4779 else {
4780 /* inspired from error.c */
4781 xmlParserInputPtr input;
4782 input = ctx->input;
4783 if ((input->filename == NULL) && (ctx->inputNr > 1))
4784 input = ctx->inputTab[ctx->inputNr - 2];
4785 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00004786 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004787 }
Daniel Veillard417be3a2003-01-20 21:26:34 +00004788 else {
4789 ret = NULL;
4790 }
4791 }
4792
4793 return ret;
4794}
4795
Daniel Veillard26f70262003-01-16 22:45:08 +00004796static void
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004797xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity,
4798 char *str)
4799{
4800 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4801
4802 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
Daniel Veillard26f70262003-01-16 22:45:08 +00004803
William M. Bracka3215c72004-07-31 16:24:01 +00004804 if (str != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004805 if (reader->errorFunc)
4806 reader->errorFunc(reader->errorFuncArg, str, severity,
4807 (xmlTextReaderLocatorPtr) ctx);
4808 xmlFree(str);
Daniel Veillard26f70262003-01-16 22:45:08 +00004809 }
4810}
4811
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004812static void
4813xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error)
4814{
4815 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
William M. Brack93d004f2004-02-03 00:14:10 +00004816
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004817 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4818
4819 if (error && reader->sErrorFunc) {
4820 reader->sErrorFunc(reader->errorFuncArg, (xmlErrorPtr) error);
4821 }
William M. Brack93d004f2004-02-03 00:14:10 +00004822}
4823
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004824static void XMLCDECL
4825xmlTextReaderError(void *ctxt, const char *msg, ...)
4826{
Daniel Veillard26f70262003-01-16 22:45:08 +00004827 va_list ap;
4828
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004829 va_start(ap, msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004830 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004831 XML_PARSER_SEVERITY_ERROR,
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004832 xmlTextReaderBuildMessage(msg, ap));
Daniel Veillard26f70262003-01-16 22:45:08 +00004833 va_end(ap);
4834
4835}
4836
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004837static void XMLCDECL
4838xmlTextReaderWarning(void *ctxt, const char *msg, ...)
4839{
Daniel Veillard26f70262003-01-16 22:45:08 +00004840 va_list ap;
4841
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004842 va_start(ap, msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004843 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004844 XML_PARSER_SEVERITY_WARNING,
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004845 xmlTextReaderBuildMessage(msg, ap));
Daniel Veillard26f70262003-01-16 22:45:08 +00004846 va_end(ap);
4847}
4848
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004849static void XMLCDECL
4850xmlTextReaderValidityError(void *ctxt, const char *msg, ...)
4851{
Daniel Veillard26f70262003-01-16 22:45:08 +00004852 va_list ap;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004853
Daniel Veillard417be3a2003-01-20 21:26:34 +00004854 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004855
Daniel Veillard417be3a2003-01-20 21:26:34 +00004856 if ((len > 1) && (msg[len - 2] != ':')) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004857 /*
4858 * some callbacks only report locator information:
4859 * skip them (mimicking behaviour in error.c)
4860 */
4861 va_start(ap, msg);
4862 xmlTextReaderGenericError(ctxt,
4863 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4864 xmlTextReaderBuildMessage(msg, ap));
4865 va_end(ap);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004866 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004867}
4868
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004869static void XMLCDECL
4870xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...)
4871{
Daniel Veillard26f70262003-01-16 22:45:08 +00004872 va_list ap;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004873
Daniel Veillard417be3a2003-01-20 21:26:34 +00004874 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004875
Daniel Veillard417be3a2003-01-20 21:26:34 +00004876 if ((len != 0) && (msg[len - 1] != ':')) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004877 /*
4878 * some callbacks only report locator information:
4879 * skip them (mimicking behaviour in error.c)
4880 */
4881 va_start(ap, msg);
4882 xmlTextReaderGenericError(ctxt,
4883 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4884 xmlTextReaderBuildMessage(msg, ap));
4885 va_end(ap);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004886 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004887}
4888
4889/**
4890 * xmlTextReaderSetErrorHandler:
4891 * @reader: the xmlTextReaderPtr used
4892 * @f: the callback function to call on error and warnings
4893 * @arg: a user argument to pass to the callback function
4894 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00004895 * Register a callback function that will be called on error and warnings.
4896 *
Daniel Veillard26f70262003-01-16 22:45:08 +00004897 * If @f is NULL, the default error and warning handlers are restored.
4898 */
4899void
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004900xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
4901 xmlTextReaderErrorFunc f, void *arg)
4902{
Daniel Veillard26f70262003-01-16 22:45:08 +00004903 if (f != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004904 reader->ctxt->sax->error = xmlTextReaderError;
4905 reader->ctxt->sax->serror = NULL;
4906 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4907 reader->ctxt->sax->warning = xmlTextReaderWarning;
4908 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4909 reader->errorFunc = f;
4910 reader->sErrorFunc = NULL;
4911 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004912#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004913 if (reader->rngValidCtxt) {
4914 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4915 xmlTextReaderValidityErrorRelay,
4916 xmlTextReaderValidityWarningRelay,
4917 reader);
4918 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4919 reader);
4920 }
4921 if (reader->xsdValidCtxt) {
4922 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4923 xmlTextReaderValidityErrorRelay,
4924 xmlTextReaderValidityWarningRelay,
4925 reader);
4926 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4927 reader);
4928 }
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004929#endif
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004930 } else {
4931 /* restore defaults */
4932 reader->ctxt->sax->error = xmlParserError;
4933 reader->ctxt->vctxt.error = xmlParserValidityError;
4934 reader->ctxt->sax->warning = xmlParserWarning;
4935 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4936 reader->errorFunc = NULL;
4937 reader->sErrorFunc = NULL;
4938 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004939#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004940 if (reader->rngValidCtxt) {
4941 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4942 reader);
4943 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4944 reader);
4945 }
4946 if (reader->xsdValidCtxt) {
4947 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4948 reader);
4949 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4950 reader);
4951 }
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004952#endif
Daniel Veillard26f70262003-01-16 22:45:08 +00004953 }
4954}
4955
Daniel Veillard417be3a2003-01-20 21:26:34 +00004956/**
William M. Brack93d004f2004-02-03 00:14:10 +00004957* xmlTextReaderSetStructuredErrorHandler:
4958 * @reader: the xmlTextReaderPtr used
4959 * @f: the callback function to call on error and warnings
4960 * @arg: a user argument to pass to the callback function
4961 *
4962 * Register a callback function that will be called on error and warnings.
4963 *
4964 * If @f is NULL, the default error and warning handlers are restored.
4965 */
4966void
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004967xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4968 xmlStructuredErrorFunc f, void *arg)
4969{
4970 if (f != NULL) {
4971 reader->ctxt->sax->error = NULL;
4972 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4973 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4974 reader->ctxt->sax->warning = xmlTextReaderWarning;
4975 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4976 reader->sErrorFunc = f;
4977 reader->errorFunc = NULL;
4978 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004979#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004980 if (reader->rngValidCtxt) {
4981 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4982 reader);
4983 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4984 xmlTextReaderValidityStructuredRelay,
4985 reader);
4986 }
4987 if (reader->xsdValidCtxt) {
4988 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4989 reader);
4990 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4991 xmlTextReaderValidityStructuredRelay,
4992 reader);
4993 }
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004994#endif
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004995 } else {
4996 /* restore defaults */
4997 reader->ctxt->sax->error = xmlParserError;
4998 reader->ctxt->sax->serror = NULL;
4999 reader->ctxt->vctxt.error = xmlParserValidityError;
5000 reader->ctxt->sax->warning = xmlParserWarning;
5001 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
5002 reader->errorFunc = NULL;
5003 reader->sErrorFunc = NULL;
5004 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00005005#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005006 if (reader->rngValidCtxt) {
5007 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
5008 reader);
5009 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
5010 reader);
5011 }
5012 if (reader->xsdValidCtxt) {
5013 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
5014 reader);
5015 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
5016 reader);
5017 }
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00005018#endif
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005019 }
William M. Brack93d004f2004-02-03 00:14:10 +00005020}
5021
5022/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00005023 * xmlTextReaderIsValid:
5024 * @reader: the xmlTextReaderPtr used
5025 *
5026 * Retrieve the validity status from the parser context
5027 *
5028 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
5029 */
5030int
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005031xmlTextReaderIsValid(xmlTextReaderPtr reader)
5032{
5033 if (reader == NULL)
5034 return (-1);
Daniel Veillardf4e55762003-04-15 23:32:22 +00005035#ifdef LIBXML_SCHEMAS_ENABLED
5036 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005037 return (reader->rngValidErrors == 0);
Daniel Veillardf10ae122005-07-10 19:03:16 +00005038 if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005039 return (reader->xsdValidErrors == 0);
Daniel Veillardf4e55762003-04-15 23:32:22 +00005040#endif
Daniel Veillard16ed5972003-11-20 18:22:31 +00005041 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005042 return (reader->ctxt->valid);
5043 return (0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00005044}
5045
5046/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00005047 * xmlTextReaderGetErrorHandler:
5048 * @reader: the xmlTextReaderPtr used
5049 * @f: the callback function or NULL is no callback has been registered
5050 * @arg: a user argument
5051 *
5052 * Retrieve the error callback function and user argument.
5053 */
Daniel Veillard26f70262003-01-16 22:45:08 +00005054void
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005055xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
5056 xmlTextReaderErrorFunc * f, void **arg)
5057{
5058 if (f != NULL)
5059 *f = reader->errorFunc;
5060 if (arg != NULL)
5061 *arg = reader->errorFuncArg;
Daniel Veillard26f70262003-01-16 22:45:08 +00005062}
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005063/************************************************************************
5064 * *
5065 * New set (2.6.0) of simpler and more flexible APIs *
5066 * *
5067 ************************************************************************/
5068
5069/**
5070 * xmlTextReaderSetup:
5071 * @reader: an XML reader
Daniel Veillarde96b47f2007-01-04 17:28:35 +00005072 * @input: xmlParserInputBufferPtr used to feed the reader, will
5073 * be destroyed with it.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005074 * @URL: the base URL to use for the document
5075 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005076 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005077 *
5078 * Setup an XML reader with new options
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005079 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005080 * Returns 0 in case of success and -1 in case of error.
5081 */
Aleksey Sanind8377642007-01-03 23:13:12 +00005082int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005083xmlTextReaderSetup(xmlTextReaderPtr reader,
5084 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005085 const char *encoding, int options)
5086{
William M. Brackd46c1ca2007-02-08 23:34:34 +00005087 if (reader == NULL) {
William M. Brackbf9a73d2007-02-09 00:07:07 +00005088 if (input != NULL)
William M. Brackd46c1ca2007-02-08 23:34:34 +00005089 xmlFreeParserInputBuffer(input);
William M. Brackbf9a73d2007-02-09 00:07:07 +00005090 return (-1);
William M. Brackd46c1ca2007-02-08 23:34:34 +00005091 }
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005092
Daniel Veillard8874b942005-08-25 13:19:21 +00005093 /*
5094 * we force the generation of compact text nodes on the reader
5095 * since usr applications should never modify the tree
5096 */
5097 options |= XML_PARSE_COMPACT;
5098
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005099 reader->doc = NULL;
5100 reader->entNr = 0;
Daniel Veillarde74d2e12003-12-09 11:35:37 +00005101 reader->parserFlags = options;
Daniel Veillardc36965d2003-12-02 10:28:48 +00005102 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005103 if ((input != NULL) && (reader->input != NULL) &&
5104 (reader->allocs & XML_TEXTREADER_INPUT)) {
5105 xmlFreeParserInputBuffer(reader->input);
5106 reader->input = NULL;
5107 reader->allocs -= XML_TEXTREADER_INPUT;
5108 }
5109 if (input != NULL) {
5110 reader->input = input;
5111 reader->allocs |= XML_TEXTREADER_INPUT;
5112 }
5113 if (reader->buffer == NULL)
Daniel Veillard8aebce32012-07-16 14:42:31 +08005114 reader->buffer = xmlBufCreateSize(100);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005115 if (reader->buffer == NULL) {
5116 xmlGenericError(xmlGenericErrorContext,
5117 "xmlTextReaderSetup : malloc failed\n");
5118 return (-1);
5119 }
5120 if (reader->sax == NULL)
5121 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
5122 if (reader->sax == NULL) {
5123 xmlGenericError(xmlGenericErrorContext,
5124 "xmlTextReaderSetup : malloc failed\n");
5125 return (-1);
5126 }
5127 xmlSAXVersion(reader->sax, 2);
5128 reader->startElement = reader->sax->startElement;
5129 reader->sax->startElement = xmlTextReaderStartElement;
5130 reader->endElement = reader->sax->endElement;
5131 reader->sax->endElement = xmlTextReaderEndElement;
5132#ifdef LIBXML_SAX1_ENABLED
5133 if (reader->sax->initialized == XML_SAX2_MAGIC) {
5134#endif /* LIBXML_SAX1_ENABLED */
5135 reader->startElementNs = reader->sax->startElementNs;
5136 reader->sax->startElementNs = xmlTextReaderStartElementNs;
5137 reader->endElementNs = reader->sax->endElementNs;
5138 reader->sax->endElementNs = xmlTextReaderEndElementNs;
5139#ifdef LIBXML_SAX1_ENABLED
5140 } else {
5141 reader->startElementNs = NULL;
5142 reader->endElementNs = NULL;
5143 }
5144#endif /* LIBXML_SAX1_ENABLED */
5145 reader->characters = reader->sax->characters;
5146 reader->sax->characters = xmlTextReaderCharacters;
5147 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
5148 reader->cdataBlock = reader->sax->cdataBlock;
5149 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
5150
5151 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5152 reader->node = NULL;
5153 reader->curnode = NULL;
5154 if (input != NULL) {
Daniel Veillard8aebce32012-07-16 14:42:31 +08005155 if (xmlBufUse(reader->input->buffer) < 4) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005156 xmlParserInputBufferRead(input, 4);
5157 }
5158 if (reader->ctxt == NULL) {
Daniel Veillard8aebce32012-07-16 14:42:31 +08005159 if (xmlBufUse(reader->input->buffer) >= 4) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005160 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
Daniel Veillard8aebce32012-07-16 14:42:31 +08005161 (const char *) xmlBufContent(reader->input->buffer),
5162 4, URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005163 reader->base = 0;
5164 reader->cur = 4;
5165 } else {
5166 reader->ctxt =
5167 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
5168 reader->base = 0;
5169 reader->cur = 0;
5170 }
5171 } else {
5172 xmlParserInputPtr inputStream;
5173 xmlParserInputBufferPtr buf;
5174 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
5175
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005176 xmlCtxtReset(reader->ctxt);
5177 buf = xmlAllocParserInputBuffer(enc);
5178 if (buf == NULL) return(-1);
5179 inputStream = xmlNewInputStream(reader->ctxt);
5180 if (inputStream == NULL) {
5181 xmlFreeParserInputBuffer(buf);
5182 return(-1);
5183 }
5184
5185 if (URL == NULL)
5186 inputStream->filename = NULL;
5187 else
5188 inputStream->filename = (char *)
5189 xmlCanonicPath((const xmlChar *) URL);
5190 inputStream->buf = buf;
Daniel Veillard61551a12012-07-16 16:28:47 +08005191 xmlBufResetInput(buf->buffer, inputStream);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005192
5193 inputPush(reader->ctxt, inputStream);
5194 reader->cur = 0;
5195 }
5196 if (reader->ctxt == NULL) {
5197 xmlGenericError(xmlGenericErrorContext,
5198 "xmlTextReaderSetup : malloc failed\n");
5199 return (-1);
5200 }
5201 }
5202 if (reader->dict != NULL) {
5203 if (reader->ctxt->dict != NULL) {
5204 if (reader->dict != reader->ctxt->dict) {
5205 xmlDictFree(reader->dict);
5206 reader->dict = reader->ctxt->dict;
5207 }
5208 } else {
5209 reader->ctxt->dict = reader->dict;
5210 }
5211 } else {
5212 if (reader->ctxt->dict == NULL)
5213 reader->ctxt->dict = xmlDictCreate();
5214 reader->dict = reader->ctxt->dict;
5215 }
5216 reader->ctxt->_private = reader;
5217 reader->ctxt->linenumbers = 1;
5218 reader->ctxt->dictNames = 1;
5219 /*
5220 * use the parser dictionnary to allocate all elements and attributes names
5221 */
5222 reader->ctxt->docdict = 1;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00005223 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005224
Daniel Veillard7899c5c2003-11-03 12:31:38 +00005225#ifdef LIBXML_XINCLUDE_ENABLED
5226 if (reader->xincctxt != NULL) {
5227 xmlXIncludeFreeContext(reader->xincctxt);
5228 reader->xincctxt = NULL;
5229 }
5230 if (options & XML_PARSE_XINCLUDE) {
5231 reader->xinclude = 1;
5232 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
5233 options -= XML_PARSE_XINCLUDE;
5234 } else
5235 reader->xinclude = 0;
5236 reader->in_xinclude = 0;
5237#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00005238#ifdef LIBXML_PATTERN_ENABLED
5239 if (reader->patternTab == NULL) {
5240 reader->patternNr = 0;
5241 reader->patternMax = 0;
5242 }
5243 while (reader->patternNr > 0) {
5244 reader->patternNr--;
5245 if (reader->patternTab[reader->patternNr] != NULL) {
5246 xmlFreePattern(reader->patternTab[reader->patternNr]);
5247 reader->patternTab[reader->patternNr] = NULL;
5248 }
5249 }
5250#endif
5251
Daniel Veillardc36965d2003-12-02 10:28:48 +00005252 if (options & XML_PARSE_DTDVALID)
5253 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
5254
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005255 xmlCtxtUseOptions(reader->ctxt, options);
5256 if (encoding != NULL) {
5257 xmlCharEncodingHandlerPtr hdlr;
5258
5259 hdlr = xmlFindCharEncodingHandler(encoding);
5260 if (hdlr != NULL)
5261 xmlSwitchToEncoding(reader->ctxt, hdlr);
5262 }
5263 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
5264 (reader->ctxt->input->filename == NULL))
5265 reader->ctxt->input->filename = (char *)
5266 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005267
5268 reader->doc = NULL;
5269
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005270 return (0);
5271}
5272
5273/**
Daniel Veillard5e094142005-02-18 19:36:12 +00005274 * xmlTextReaderByteConsumed:
5275 * @reader: an XML reader
5276 *
5277 * This function provides the current index of the parser used
5278 * by the reader, relative to the start of the current entity.
5279 * This function actually just wraps a call to xmlBytesConsumed()
5280 * for the parser context associated with the reader.
5281 * See xmlBytesConsumed() for more information.
5282 *
5283 * Returns the index in bytes from the beginning of the entity or -1
5284 * in case the index could not be computed.
5285 */
5286long
5287xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
5288 if ((reader == NULL) || (reader->ctxt == NULL))
5289 return(-1);
5290 return(xmlByteConsumed(reader->ctxt));
5291}
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005292
Daniel Veillard5e094142005-02-18 19:36:12 +00005293
5294/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005295 * xmlReaderWalker:
5296 * @doc: a preparsed document
5297 *
5298 * Create an xmltextReader for a preparsed document.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005299 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005300 * Returns the new reader or NULL in case of error.
5301 */
5302xmlTextReaderPtr
5303xmlReaderWalker(xmlDocPtr doc)
5304{
5305 xmlTextReaderPtr ret;
5306
5307 if (doc == NULL)
5308 return(NULL);
5309
5310 ret = xmlMalloc(sizeof(xmlTextReader));
5311 if (ret == NULL) {
5312 xmlGenericError(xmlGenericErrorContext,
5313 "xmlNewTextReader : malloc failed\n");
5314 return(NULL);
5315 }
5316 memset(ret, 0, sizeof(xmlTextReader));
5317 ret->entNr = 0;
5318 ret->input = NULL;
5319 ret->mode = XML_TEXTREADER_MODE_INITIAL;
5320 ret->node = NULL;
5321 ret->curnode = NULL;
5322 ret->base = 0;
5323 ret->cur = 0;
5324 ret->allocs = XML_TEXTREADER_CTXT;
5325 ret->doc = doc;
5326 ret->state = XML_TEXTREADER_START;
5327 ret->dict = xmlDictCreate();
5328 return(ret);
5329}
5330
5331/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005332 * xmlReaderForDoc:
5333 * @cur: a pointer to a zero terminated string
5334 * @URL: the base URL to use for the document
5335 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005336 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005337 *
5338 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005339 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005340 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005341 * Returns the new reader or NULL in case of error.
5342 */
5343xmlTextReaderPtr
5344xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
5345 int options)
5346{
5347 int len;
5348
5349 if (cur == NULL)
5350 return (NULL);
5351 len = xmlStrlen(cur);
5352
5353 return (xmlReaderForMemory
5354 ((const char *) cur, len, URL, encoding, options));
5355}
5356
5357/**
5358 * xmlReaderForFile:
5359 * @filename: a file or URL
5360 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005361 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005362 *
5363 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005364 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005365 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005366 * Returns the new reader or NULL in case of error.
5367 */
5368xmlTextReaderPtr
5369xmlReaderForFile(const char *filename, const char *encoding, int options)
5370{
5371 xmlTextReaderPtr reader;
5372
5373 reader = xmlNewTextReaderFilename(filename);
5374 if (reader == NULL)
5375 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005376 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005377 return (reader);
5378}
5379
5380/**
5381 * xmlReaderForMemory:
5382 * @buffer: a pointer to a char array
5383 * @size: the size of the array
5384 * @URL: the base URL to use for the document
5385 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005386 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005387 *
5388 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005389 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005390 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005391 * Returns the new reader or NULL in case of error.
5392 */
5393xmlTextReaderPtr
5394xmlReaderForMemory(const char *buffer, int size, const char *URL,
5395 const char *encoding, int options)
5396{
5397 xmlTextReaderPtr reader;
5398 xmlParserInputBufferPtr buf;
5399
Daniel Veillard21924522004-02-19 16:37:07 +00005400 buf = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005401 XML_CHAR_ENCODING_NONE);
5402 if (buf == NULL) {
5403 return (NULL);
5404 }
5405 reader = xmlNewTextReader(buf, URL);
5406 if (reader == NULL) {
5407 xmlFreeParserInputBuffer(buf);
5408 return (NULL);
5409 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005410 reader->allocs |= XML_TEXTREADER_INPUT;
5411 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005412 return (reader);
5413}
5414
5415/**
5416 * xmlReaderForFd:
5417 * @fd: an open file descriptor
5418 * @URL: the base URL to use for the document
5419 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005420 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005421 *
5422 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005423 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005424 * NOTE that the file descriptor will not be closed when the
5425 * reader is closed or reset.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005426 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005427 * Returns the new reader or NULL in case of error.
5428 */
5429xmlTextReaderPtr
5430xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
5431{
5432 xmlTextReaderPtr reader;
5433 xmlParserInputBufferPtr input;
5434
5435 if (fd < 0)
5436 return (NULL);
5437
5438 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5439 if (input == NULL)
5440 return (NULL);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005441 input->closecallback = NULL;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005442 reader = xmlNewTextReader(input, URL);
5443 if (reader == NULL) {
5444 xmlFreeParserInputBuffer(input);
5445 return (NULL);
5446 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005447 reader->allocs |= XML_TEXTREADER_INPUT;
5448 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005449 return (reader);
5450}
5451
5452/**
5453 * xmlReaderForIO:
5454 * @ioread: an I/O read function
5455 * @ioclose: an I/O close function
5456 * @ioctx: an I/O handler
5457 * @URL: the base URL to use for the document
5458 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005459 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005460 *
5461 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005462 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005463 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005464 * Returns the new reader or NULL in case of error.
5465 */
5466xmlTextReaderPtr
5467xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
5468 void *ioctx, const char *URL, const char *encoding,
5469 int options)
5470{
5471 xmlTextReaderPtr reader;
5472 xmlParserInputBufferPtr input;
5473
5474 if (ioread == NULL)
5475 return (NULL);
5476
5477 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5478 XML_CHAR_ENCODING_NONE);
Lin Yi-Li24464be2012-05-10 16:14:55 +08005479 if (input == NULL) {
5480 if (ioclose != NULL)
5481 ioclose(ioctx);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005482 return (NULL);
Lin Yi-Li24464be2012-05-10 16:14:55 +08005483 }
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005484 reader = xmlNewTextReader(input, URL);
5485 if (reader == NULL) {
5486 xmlFreeParserInputBuffer(input);
5487 return (NULL);
5488 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005489 reader->allocs |= XML_TEXTREADER_INPUT;
5490 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005491 return (reader);
5492}
5493
5494/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005495 * xmlReaderNewWalker:
5496 * @reader: an XML reader
5497 * @doc: a preparsed document
5498 *
5499 * Setup an xmltextReader to parse a preparsed XML document.
5500 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005501 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005502 * Returns 0 in case of success and -1 in case of error
5503 */
5504int
5505xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
5506{
5507 if (doc == NULL)
5508 return (-1);
5509 if (reader == NULL)
5510 return (-1);
5511
Daniel Veillarddd6d3002004-11-03 14:20:29 +00005512 if (reader->input != NULL) {
5513 xmlFreeParserInputBuffer(reader->input);
5514 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005515 if (reader->ctxt != NULL) {
5516 xmlCtxtReset(reader->ctxt);
5517 }
5518
5519 reader->entNr = 0;
5520 reader->input = NULL;
5521 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5522 reader->node = NULL;
5523 reader->curnode = NULL;
5524 reader->base = 0;
5525 reader->cur = 0;
5526 reader->allocs = XML_TEXTREADER_CTXT;
5527 reader->doc = doc;
5528 reader->state = XML_TEXTREADER_START;
5529 if (reader->dict == NULL) {
5530 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
5531 reader->dict = reader->ctxt->dict;
5532 else
5533 reader->dict = xmlDictCreate();
5534 }
5535 return(0);
5536}
5537
5538/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005539 * xmlReaderNewDoc:
5540 * @reader: an XML reader
5541 * @cur: a pointer to a zero terminated string
5542 * @URL: the base URL to use for the document
5543 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005544 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005545 *
5546 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005547 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005548 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005549 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005550 * Returns 0 in case of success and -1 in case of error
5551 */
5552int
5553xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
5554 const char *URL, const char *encoding, int options)
5555{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005556
5557 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005558
5559 if (cur == NULL)
5560 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005561 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005562 return (-1);
5563
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005564 len = xmlStrlen(cur);
5565 return (xmlReaderNewMemory(reader, (const char *)cur, len,
5566 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005567}
5568
5569/**
5570 * xmlReaderNewFile:
5571 * @reader: an XML reader
5572 * @filename: a file or URL
5573 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005574 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005575 *
5576 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005577 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005578 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005579 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005580 * Returns 0 in case of success and -1 in case of error
5581 */
5582int
5583xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
5584 const char *encoding, int options)
5585{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005586 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005587
5588 if (filename == NULL)
5589 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005590 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005591 return (-1);
5592
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005593 input =
5594 xmlParserInputBufferCreateFilename(filename,
5595 XML_CHAR_ENCODING_NONE);
5596 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005597 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005598 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005599}
5600
5601/**
5602 * xmlReaderNewMemory:
5603 * @reader: an XML reader
5604 * @buffer: a pointer to a char array
5605 * @size: the size of the array
5606 * @URL: the base URL to use for the document
5607 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005608 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005609 *
5610 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005611 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005612 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005613 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005614 * Returns 0 in case of success and -1 in case of error
5615 */
5616int
5617xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
5618 const char *URL, const char *encoding, int options)
5619{
5620 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005621
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005622 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005623 return (-1);
5624 if (buffer == NULL)
5625 return (-1);
5626
Daniel Veillard21924522004-02-19 16:37:07 +00005627 input = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005628 XML_CHAR_ENCODING_NONE);
5629 if (input == NULL) {
5630 return (-1);
5631 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005632 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005633}
5634
5635/**
5636 * xmlReaderNewFd:
5637 * @reader: an XML reader
5638 * @fd: an open file descriptor
5639 * @URL: the base URL to use for the document
5640 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005641 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005642 *
5643 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005644 * NOTE that the file descriptor will not be closed when the
5645 * reader is closed or reset.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005646 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005647 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005648 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005649 * Returns 0 in case of success and -1 in case of error
5650 */
5651int
5652xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
5653 const char *URL, const char *encoding, int options)
5654{
5655 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005656
5657 if (fd < 0)
5658 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005659 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005660 return (-1);
5661
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005662 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5663 if (input == NULL)
5664 return (-1);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005665 input->closecallback = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005666 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005667}
5668
5669/**
5670 * xmlReaderNewIO:
5671 * @reader: an XML reader
5672 * @ioread: an I/O read function
5673 * @ioclose: an I/O close function
5674 * @ioctx: an I/O handler
5675 * @URL: the base URL to use for the document
5676 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005677 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005678 *
5679 * Setup an xmltextReader to parse an XML document from I/O functions
5680 * and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005681 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005682 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005683 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005684 * Returns 0 in case of success and -1 in case of error
5685 */
5686int
5687xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
5688 xmlInputCloseCallback ioclose, void *ioctx,
5689 const char *URL, const char *encoding, int options)
5690{
5691 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005692
5693 if (ioread == NULL)
5694 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005695 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005696 return (-1);
5697
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005698 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5699 XML_CHAR_ENCODING_NONE);
Lin Yi-Li24464be2012-05-10 16:14:55 +08005700 if (input == NULL) {
5701 if (ioclose != NULL)
5702 ioclose(ioctx);
Daniel Veillard2c437da2012-05-11 12:08:15 +08005703 return (-1);
Lin Yi-Li24464be2012-05-10 16:14:55 +08005704 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005705 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005706}
Lin Yi-Li24464be2012-05-10 16:14:55 +08005707
Daniel Veillard26f70262003-01-16 22:45:08 +00005708/************************************************************************
5709 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005710 * Utilities *
5711 * *
5712 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005713#ifdef NOT_USED_YET
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005714
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005715/**
5716 * xmlBase64Decode:
5717 * @in: the input buffer
5718 * @inlen: the size of the input (in), the size read from it (out)
5719 * @to: the output buffer
5720 * @tolen: the size of the output (in), the size written to (out)
5721 *
5722 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00005723 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005724 *
5725 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
5726 * 2 if there wasn't enough space on the output or -1 in case of error.
5727 */
5728static int
5729xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005730 unsigned char *to, unsigned long *tolen)
5731{
5732 unsigned long incur; /* current index in in[] */
5733
5734 unsigned long inblk; /* last block index in in[] */
5735
5736 unsigned long outcur; /* current index in out[] */
5737
5738 unsigned long inmax; /* size of in[] */
5739
5740 unsigned long outmax; /* size of out[] */
5741
5742 unsigned char cur; /* the current value read from in[] */
5743
5744 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
5745
5746 int nbintmp; /* number of byte in intmp[] */
5747
5748 int is_ignore; /* cur should be ignored */
5749
5750 int is_end = 0; /* the end of the base64 was found */
5751
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005752 int retval = 1;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005753
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005754 int i;
5755
5756 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005757 return (-1);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005758
5759 incur = 0;
5760 inblk = 0;
5761 outcur = 0;
5762 inmax = *inlen;
5763 outmax = *tolen;
5764 nbintmp = 0;
5765
5766 while (1) {
5767 if (incur >= inmax)
5768 break;
5769 cur = in[incur++];
5770 is_ignore = 0;
5771 if ((cur >= 'A') && (cur <= 'Z'))
5772 cur = cur - 'A';
5773 else if ((cur >= 'a') && (cur <= 'z'))
5774 cur = cur - 'a' + 26;
5775 else if ((cur >= '0') && (cur <= '9'))
5776 cur = cur - '0' + 52;
5777 else if (cur == '+')
5778 cur = 62;
5779 else if (cur == '/')
5780 cur = 63;
5781 else if (cur == '.')
5782 cur = 0;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005783 else if (cur == '=') /*no op , end of the base64 stream */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005784 is_end = 1;
5785 else {
5786 is_ignore = 1;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005787 if (nbintmp == 0)
5788 inblk = incur;
5789 }
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005790
5791 if (!is_ignore) {
5792 int nbouttmp = 3;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005793
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005794 int is_break = 0;
5795
5796 if (is_end) {
5797 if (nbintmp == 0)
5798 break;
5799 if ((nbintmp == 1) || (nbintmp == 2))
5800 nbouttmp = 1;
5801 else
5802 nbouttmp = 2;
5803 nbintmp = 3;
5804 is_break = 1;
5805 }
5806 intmp[nbintmp++] = cur;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005807 /*
5808 * if intmp is full, push the 4byte sequence as a 3 byte
5809 * sequence out
5810 */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005811 if (nbintmp == 4) {
5812 nbintmp = 0;
5813 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
5814 outtmp[1] =
5815 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
5816 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005817 if (outcur + 3 >= outmax) {
5818 retval = 2;
5819 break;
5820 }
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005821
5822 for (i = 0; i < nbouttmp; i++)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005823 to[outcur++] = outtmp[i];
5824 inblk = incur;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005825 }
5826
5827 if (is_break) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005828 retval = 0;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005829 break;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005830 }
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005831 }
5832 }
5833
5834 *tolen = outcur;
5835 *inlen = inblk;
5836 return (retval);
5837}
5838
5839/*
5840 * Test routine for the xmlBase64Decode function
5841 */
5842#if 0
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005843int
5844main(int argc, char **argv)
5845{
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005846 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005847
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005848 char output[100];
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005849
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005850 char output2[100];
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005851
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005852 char output3[100];
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005853
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005854 unsigned long inlen = strlen(input);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005855
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005856 unsigned long outlen = 100;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005857
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005858 int ret;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005859
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005860 unsigned long cons, tmp, tmp2, prod;
5861
5862 /*
5863 * Direct
5864 */
5865 ret = xmlBase64Decode(input, &inlen, output, &outlen);
5866
5867 output[outlen] = 0;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005868 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen,
5869 outlen, output)indent: Standard input:179: Error:Unmatched #endif
5870;
5871
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005872 /*
5873 * output chunking
5874 */
5875 cons = 0;
5876 prod = 0;
5877 while (cons < inlen) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005878 tmp = 5;
5879 tmp2 = inlen - cons;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005880
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005881 printf("%ld %ld\n", cons, prod);
5882 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
5883 cons += tmp2;
5884 prod += tmp;
5885 printf("%ld %ld\n", cons, prod);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005886 }
5887 output2[outlen] = 0;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005888 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
5889 prod, output2);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005890
5891 /*
5892 * input chunking
5893 */
5894 cons = 0;
5895 prod = 0;
5896 while (cons < inlen) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005897 tmp = 100 - prod;
5898 tmp2 = inlen - cons;
5899 if (tmp2 > 5)
5900 tmp2 = 5;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005901
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005902 printf("%ld %ld\n", cons, prod);
5903 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
5904 cons += tmp2;
5905 prod += tmp;
5906 printf("%ld %ld\n", cons, prod);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005907 }
5908 output3[outlen] = 0;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005909 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
5910 prod, output3);
5911 return (0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005912
5913}
5914#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005915#endif /* NOT_USED_YET */
Daniel Veillard5d4644e2005-04-01 13:11:58 +00005916#define bottom_xmlreader
5917#include "elfgcchack.h"
Daniel Veillard81273902003-09-30 00:43:48 +00005918#endif /* LIBXML_READER_ENABLED */