Home | History | Annotate | Download | only in src
      1 /*
      2  * xmlreader.c: implements the xmlTextReader streaming node API
      3  *
      4  * NOTE:
      5  *   XmlTextReader.Normalization Property won't be supported, since
      6  *     it makes the parser non compliant to the XML recommendation
      7  *
      8  * See Copyright for the status of this software.
      9  *
     10  * daniel (at) veillard.com
     11  */
     12 
     13 /*
     14  * TODOs:
     15  *   - XML Schemas validation
     16  */
     17 #define IN_LIBXML
     18 #include "libxml.h"
     19 
     20 #ifdef LIBXML_READER_ENABLED
     21 #include <string.h> /* for memset() only ! */
     22 #include <stdarg.h>
     23 
     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>
     34 #include <libxml/parserInternals.h>
     35 #ifdef LIBXML_SCHEMAS_ENABLED
     36 #include <libxml/relaxng.h>
     37 #include <libxml/xmlschemas.h>
     38 #endif
     39 #include <libxml/uri.h>
     40 #ifdef LIBXML_XINCLUDE_ENABLED
     41 #include <libxml/xinclude.h>
     42 #endif
     43 #ifdef LIBXML_PATTERN_ENABLED
     44 #include <libxml/pattern.h>
     45 #endif
     46 
     47 #define MAX_ERR_MSG_SIZE 64000
     48 
     49 /*
     50  * The following VA_COPY was coded following an example in
     51  * the Samba project.  It may not be sufficient for some
     52  * esoteric implementations of va_list (i.e. it may need
     53  * something involving a memcpy) but (hopefully) will be
     54  * sufficient for libxml2.
     55  */
     56 #ifndef VA_COPY
     57   #ifdef HAVE_VA_COPY
     58     #define VA_COPY(dest, src) va_copy(dest, src)
     59   #else
     60     #ifdef HAVE___VA_COPY
     61       #define VA_COPY(dest,src) __va_copy(dest, src)
     62     #else
     63       #define VA_COPY(dest,src) (dest) = (src)
     64     #endif
     65   #endif
     66 #endif
     67 
     68 /* #define DEBUG_CALLBACKS */
     69 /* #define DEBUG_READER */
     70 
     71 /**
     72  * TODO:
     73  *
     74  * macro to flag unimplemented blocks
     75  */
     76 #define TODO								\
     77     xmlGenericError(xmlGenericErrorContext,				\
     78 	    "Unimplemented block at %s:%d\n",				\
     79             __FILE__, __LINE__);
     80 
     81 #ifdef DEBUG_READER
     82 #define DUMP_READER xmlTextReaderDebug(reader);
     83 #else
     84 #define DUMP_READER
     85 #endif
     86 
     87 #define CHUNK_SIZE 512
     88 /************************************************************************
     89  *									*
     90  *	The parser: maps the Text Reader API on top of the existing	*
     91  *		parsing routines building a tree			*
     92  *									*
     93  ************************************************************************/
     94 
     95 #define XML_TEXTREADER_INPUT	1
     96 #define XML_TEXTREADER_CTXT	2
     97 
     98 typedef enum {
     99     XML_TEXTREADER_NONE = -1,
    100     XML_TEXTREADER_START= 0,
    101     XML_TEXTREADER_ELEMENT= 1,
    102     XML_TEXTREADER_END= 2,
    103     XML_TEXTREADER_EMPTY= 3,
    104     XML_TEXTREADER_BACKTRACK= 4,
    105     XML_TEXTREADER_DONE= 5,
    106     XML_TEXTREADER_ERROR= 6
    107 } xmlTextReaderState;
    108 
    109 typedef enum {
    110     XML_TEXTREADER_NOT_VALIDATE = 0,
    111     XML_TEXTREADER_VALIDATE_DTD = 1,
    112     XML_TEXTREADER_VALIDATE_RNG = 2,
    113     XML_TEXTREADER_VALIDATE_XSD = 4
    114 } xmlTextReaderValidate;
    115 
    116 struct _xmlTextReader {
    117     int				mode;	/* the parsing mode */
    118     xmlDocPtr			doc;    /* when walking an existing doc */
    119     xmlTextReaderValidate       validate;/* is there any validation */
    120     int				allocs;	/* what structure were deallocated */
    121     xmlTextReaderState		state;
    122     xmlParserCtxtPtr		ctxt;	/* the parser context */
    123     xmlSAXHandlerPtr		sax;	/* the parser SAX callbacks */
    124     xmlParserInputBufferPtr	input;	/* the input */
    125     startElementSAXFunc		startElement;/* initial SAX callbacks */
    126     endElementSAXFunc		endElement;  /* idem */
    127     startElementNsSAX2Func	startElementNs;/* idem */
    128     endElementNsSAX2Func	endElementNs;  /* idem */
    129     charactersSAXFunc		characters;
    130     cdataBlockSAXFunc		cdataBlock;
    131     unsigned int		base;	/* base of the segment in the input */
    132     unsigned int		cur;	/* current position in the input */
    133     xmlNodePtr			node;	/* current node */
    134     xmlNodePtr			curnode;/* current attribute node */
    135     int				depth;  /* depth of the current node */
    136     xmlNodePtr			faketext;/* fake xmlNs chld */
    137     int				preserve;/* preserve the resulting document */
    138     xmlBufferPtr		buffer; /* used to return const xmlChar * */
    139     xmlDictPtr			dict;	/* the context dictionnary */
    140 
    141     /* entity stack when traversing entities content */
    142     xmlNodePtr         ent;          /* Current Entity Ref Node */
    143     int                entNr;        /* Depth of the entities stack */
    144     int                entMax;       /* Max depth of the entities stack */
    145     xmlNodePtr        *entTab;       /* array of entities */
    146 
    147     /* error handling */
    148     xmlTextReaderErrorFunc errorFunc;    /* callback function */
    149     void                  *errorFuncArg; /* callback function user argument */
    150 
    151 #ifdef LIBXML_SCHEMAS_ENABLED
    152     /* Handling of RelaxNG validation */
    153     xmlRelaxNGPtr          rngSchemas;	/* The Relax NG schemas */
    154     xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */
    155     int                    rngValidErrors;/* The number of errors detected */
    156     xmlNodePtr             rngFullNode;	/* the node if RNG not progressive */
    157     /* Handling of Schemas validation */
    158     xmlSchemaPtr          xsdSchemas;	/* The Schemas schemas */
    159     xmlSchemaValidCtxtPtr xsdValidCtxt;/* The Schemas validation context */
    160     int                   xsdPreserveCtxt; /* 1 if the context was provided by the user */
    161     int                   xsdValidErrors;/* The number of errors detected */
    162     xmlSchemaSAXPlugPtr   xsdPlug;	/* the schemas plug in SAX pipeline */
    163 #endif
    164 #ifdef LIBXML_XINCLUDE_ENABLED
    165     /* Handling of XInclude processing */
    166     int                xinclude;	/* is xinclude asked for */
    167     const xmlChar *    xinclude_name;	/* the xinclude name from dict */
    168     xmlXIncludeCtxtPtr xincctxt;	/* the xinclude context */
    169     int                in_xinclude;	/* counts for xinclude */
    170 #endif
    171 #ifdef LIBXML_PATTERN_ENABLED
    172     int                patternNr;       /* number of preserve patterns */
    173     int                patternMax;      /* max preserve patterns */
    174     xmlPatternPtr     *patternTab;      /* array of preserve patterns */
    175 #endif
    176     int                preserves;	/* level of preserves */
    177     int                parserFlags;	/* the set of options set */
    178     /* Structured error handling */
    179     xmlStructuredErrorFunc sErrorFunc;  /* callback function */
    180 };
    181 
    182 #define NODE_IS_EMPTY		0x1
    183 #define NODE_IS_PRESERVED	0x2
    184 #define NODE_IS_SPRESERVED	0x4
    185 
    186 /**
    187  * CONSTSTR:
    188  *
    189  * Macro used to return an interned string
    190  */
    191 #define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
    192 #define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
    193 
    194 static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
    195 static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
    196 
    197 /************************************************************************
    198  *									*
    199  *	Our own version of the freeing routines as we recycle nodes	*
    200  *									*
    201  ************************************************************************/
    202 /**
    203  * DICT_FREE:
    204  * @str:  a string
    205  *
    206  * Free a string if it is not owned by the "dict" dictionnary in the
    207  * current scope
    208  */
    209 #define DICT_FREE(str)						\
    210 	if ((str) && ((!dict) ||				\
    211 	    (xmlDictOwns(dict, (const xmlChar *)(str)) == 0)))	\
    212 	    xmlFree((char *)(str));
    213 
    214 static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
    215 static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
    216 
    217 /**
    218  * xmlFreeID:
    219  * @not:  A id
    220  *
    221  * Deallocate the memory used by an id definition
    222  */
    223 static void
    224 xmlFreeID(xmlIDPtr id) {
    225     xmlDictPtr dict = NULL;
    226 
    227     if (id == NULL) return;
    228 
    229     if (id->doc != NULL)
    230         dict = id->doc->dict;
    231 
    232     if (id->value != NULL)
    233 	DICT_FREE(id->value)
    234     xmlFree(id);
    235 }
    236 
    237 /**
    238  * xmlTextReaderRemoveID:
    239  * @doc:  the document
    240  * @attr:  the attribute
    241  *
    242  * Remove the given attribute from the ID table maintained internally.
    243  *
    244  * Returns -1 if the lookup failed and 0 otherwise
    245  */
    246 static int
    247 xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
    248     xmlIDTablePtr table;
    249     xmlIDPtr id;
    250     xmlChar *ID;
    251 
    252     if (doc == NULL) return(-1);
    253     if (attr == NULL) return(-1);
    254     table = (xmlIDTablePtr) doc->ids;
    255     if (table == NULL)
    256         return(-1);
    257 
    258     ID = xmlNodeListGetString(doc, attr->children, 1);
    259     if (ID == NULL)
    260 	return(-1);
    261     id = xmlHashLookup(table, ID);
    262     xmlFree(ID);
    263     if (id == NULL || id->attr != attr) {
    264 	return(-1);
    265     }
    266     id->name = attr->name;
    267     id->attr = NULL;
    268     return(0);
    269 }
    270 
    271 /**
    272  * xmlTextReaderFreeProp:
    273  * @reader:  the xmlTextReaderPtr used
    274  * @cur:  the node
    275  *
    276  * Free a node.
    277  */
    278 static void
    279 xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
    280     xmlDictPtr dict;
    281 
    282     dict = reader->ctxt->dict;
    283     if (cur == NULL) return;
    284 
    285     if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
    286 	xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
    287 
    288     /* Check for ID removal -> leading to invalid references ! */
    289     if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
    290 	((cur->parent->doc->intSubset != NULL) ||
    291 	 (cur->parent->doc->extSubset != NULL))) {
    292         if (xmlIsID(cur->parent->doc, cur->parent, cur))
    293 	    xmlTextReaderRemoveID(cur->parent->doc, cur);
    294     }
    295     if (cur->children != NULL)
    296         xmlTextReaderFreeNodeList(reader, cur->children);
    297 
    298     DICT_FREE(cur->name);
    299     if ((reader != NULL) && (reader->ctxt != NULL) &&
    300         (reader->ctxt->freeAttrsNr < 100)) {
    301         cur->next = reader->ctxt->freeAttrs;
    302 	reader->ctxt->freeAttrs = cur;
    303 	reader->ctxt->freeAttrsNr++;
    304     } else {
    305 	xmlFree(cur);
    306     }
    307 }
    308 
    309 /**
    310  * xmlTextReaderFreePropList:
    311  * @reader:  the xmlTextReaderPtr used
    312  * @cur:  the first property in the list
    313  *
    314  * Free a property and all its siblings, all the children are freed too.
    315  */
    316 static void
    317 xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
    318     xmlAttrPtr next;
    319     if (cur == NULL) return;
    320     while (cur != NULL) {
    321         next = cur->next;
    322         xmlTextReaderFreeProp(reader, cur);
    323 	cur = next;
    324     }
    325 }
    326 
    327 /**
    328  * xmlTextReaderFreeNodeList:
    329  * @reader:  the xmlTextReaderPtr used
    330  * @cur:  the first node in the list
    331  *
    332  * Free a node and all its siblings, this is a recursive behaviour, all
    333  * the children are freed too.
    334  */
    335 static void
    336 xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
    337     xmlNodePtr next;
    338     xmlDictPtr dict;
    339 
    340     dict = reader->ctxt->dict;
    341     if (cur == NULL) return;
    342     if (cur->type == XML_NAMESPACE_DECL) {
    343 	xmlFreeNsList((xmlNsPtr) cur);
    344 	return;
    345     }
    346     if ((cur->type == XML_DOCUMENT_NODE) ||
    347 	(cur->type == XML_HTML_DOCUMENT_NODE)) {
    348 	xmlFreeDoc((xmlDocPtr) cur);
    349 	return;
    350     }
    351     while (cur != NULL) {
    352         next = cur->next;
    353 	/* unroll to speed up freeing the document */
    354 	if (cur->type != XML_DTD_NODE) {
    355 
    356 	    if ((cur->children != NULL) &&
    357 		(cur->type != XML_ENTITY_REF_NODE)) {
    358 		if (cur->children->parent == cur)
    359 		    xmlTextReaderFreeNodeList(reader, cur->children);
    360 		cur->children = NULL;
    361 	    }
    362 
    363 	    if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
    364 		xmlDeregisterNodeDefaultValue(cur);
    365 
    366 	    if (((cur->type == XML_ELEMENT_NODE) ||
    367 		 (cur->type == XML_XINCLUDE_START) ||
    368 		 (cur->type == XML_XINCLUDE_END)) &&
    369 		(cur->properties != NULL))
    370 		xmlTextReaderFreePropList(reader, cur->properties);
    371 	    if ((cur->content != (xmlChar *) &(cur->properties)) &&
    372 	        (cur->type != XML_ELEMENT_NODE) &&
    373 		(cur->type != XML_XINCLUDE_START) &&
    374 		(cur->type != XML_XINCLUDE_END) &&
    375 		(cur->type != XML_ENTITY_REF_NODE)) {
    376 		DICT_FREE(cur->content);
    377 	    }
    378 	    if (((cur->type == XML_ELEMENT_NODE) ||
    379 	         (cur->type == XML_XINCLUDE_START) ||
    380 		 (cur->type == XML_XINCLUDE_END)) &&
    381 		(cur->nsDef != NULL))
    382 		xmlFreeNsList(cur->nsDef);
    383 
    384 	    /*
    385 	     * we don't free element names here they are interned now
    386 	     */
    387 	    if ((cur->type != XML_TEXT_NODE) &&
    388 		(cur->type != XML_COMMENT_NODE))
    389 		DICT_FREE(cur->name);
    390 	    if (((cur->type == XML_ELEMENT_NODE) ||
    391 		 (cur->type == XML_TEXT_NODE)) &&
    392 	        (reader != NULL) && (reader->ctxt != NULL) &&
    393 		(reader->ctxt->freeElemsNr < 100)) {
    394 	        cur->next = reader->ctxt->freeElems;
    395 		reader->ctxt->freeElems = cur;
    396 		reader->ctxt->freeElemsNr++;
    397 	    } else {
    398 		xmlFree(cur);
    399 	    }
    400 	}
    401 	cur = next;
    402     }
    403 }
    404 
    405 /**
    406  * xmlTextReaderFreeNode:
    407  * @reader:  the xmlTextReaderPtr used
    408  * @cur:  the node
    409  *
    410  * Free a node, this is a recursive behaviour, all the children are freed too.
    411  * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
    412  */
    413 static void
    414 xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
    415     xmlDictPtr dict;
    416 
    417     dict = reader->ctxt->dict;
    418     if (cur->type == XML_DTD_NODE) {
    419 	xmlFreeDtd((xmlDtdPtr) cur);
    420 	return;
    421     }
    422     if (cur->type == XML_NAMESPACE_DECL) {
    423 	xmlFreeNs((xmlNsPtr) cur);
    424         return;
    425     }
    426     if (cur->type == XML_ATTRIBUTE_NODE) {
    427 	xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
    428 	return;
    429     }
    430 
    431     if ((cur->children != NULL) &&
    432 	(cur->type != XML_ENTITY_REF_NODE)) {
    433 	if (cur->children->parent == cur)
    434 	    xmlTextReaderFreeNodeList(reader, cur->children);
    435 	cur->children = NULL;
    436     }
    437 
    438     if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
    439 	xmlDeregisterNodeDefaultValue(cur);
    440 
    441     if (((cur->type == XML_ELEMENT_NODE) ||
    442 	 (cur->type == XML_XINCLUDE_START) ||
    443 	 (cur->type == XML_XINCLUDE_END)) &&
    444 	(cur->properties != NULL))
    445 	xmlTextReaderFreePropList(reader, cur->properties);
    446     if ((cur->content != (xmlChar *) &(cur->properties)) &&
    447         (cur->type != XML_ELEMENT_NODE) &&
    448 	(cur->type != XML_XINCLUDE_START) &&
    449 	(cur->type != XML_XINCLUDE_END) &&
    450 	(cur->type != XML_ENTITY_REF_NODE)) {
    451 	DICT_FREE(cur->content);
    452     }
    453     if (((cur->type == XML_ELEMENT_NODE) ||
    454 	 (cur->type == XML_XINCLUDE_START) ||
    455 	 (cur->type == XML_XINCLUDE_END)) &&
    456 	(cur->nsDef != NULL))
    457 	xmlFreeNsList(cur->nsDef);
    458 
    459     /*
    460      * we don't free names here they are interned now
    461      */
    462     if ((cur->type != XML_TEXT_NODE) &&
    463         (cur->type != XML_COMMENT_NODE))
    464 	DICT_FREE(cur->name);
    465 
    466     if (((cur->type == XML_ELEMENT_NODE) ||
    467 	 (cur->type == XML_TEXT_NODE)) &&
    468 	(reader != NULL) && (reader->ctxt != NULL) &&
    469 	(reader->ctxt->freeElemsNr < 100)) {
    470 	cur->next = reader->ctxt->freeElems;
    471 	reader->ctxt->freeElems = cur;
    472 	reader->ctxt->freeElemsNr++;
    473     } else {
    474 	xmlFree(cur);
    475     }
    476 }
    477 
    478 /**
    479  * xmlTextReaderFreeIDTable:
    480  * @table:  An id table
    481  *
    482  * Deallocate the memory used by an ID hash table.
    483  */
    484 static void
    485 xmlTextReaderFreeIDTable(xmlIDTablePtr table) {
    486     xmlHashFree(table, (xmlHashDeallocator) xmlFreeID);
    487 }
    488 
    489 /**
    490  * xmlTextReaderFreeDoc:
    491  * @reader:  the xmlTextReaderPtr used
    492  * @cur:  pointer to the document
    493  *
    494  * Free up all the structures used by a document, tree included.
    495  */
    496 static void
    497 xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
    498     xmlDtdPtr extSubset, intSubset;
    499 
    500     if (cur == NULL) return;
    501 
    502     if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
    503 	xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
    504 
    505     /*
    506      * Do this before freeing the children list to avoid ID lookups
    507      */
    508     if (cur->ids != NULL) xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids);
    509     cur->ids = NULL;
    510     if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
    511     cur->refs = NULL;
    512     extSubset = cur->extSubset;
    513     intSubset = cur->intSubset;
    514     if (intSubset == extSubset)
    515 	extSubset = NULL;
    516     if (extSubset != NULL) {
    517 	xmlUnlinkNode((xmlNodePtr) cur->extSubset);
    518 	cur->extSubset = NULL;
    519 	xmlFreeDtd(extSubset);
    520     }
    521     if (intSubset != NULL) {
    522 	xmlUnlinkNode((xmlNodePtr) cur->intSubset);
    523 	cur->intSubset = NULL;
    524 	xmlFreeDtd(intSubset);
    525     }
    526 
    527     if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
    528 
    529     if (cur->version != NULL) xmlFree((char *) cur->version);
    530     if (cur->name != NULL) xmlFree((char *) cur->name);
    531     if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
    532     if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
    533     if (cur->URL != NULL) xmlFree((char *) cur->URL);
    534     if (cur->dict != NULL) xmlDictFree(cur->dict);
    535 
    536     xmlFree(cur);
    537 }
    538 
    539 /************************************************************************
    540  *									*
    541  *			The reader core parser				*
    542  *									*
    543  ************************************************************************/
    544 #ifdef DEBUG_READER
    545 static void
    546 xmlTextReaderDebug(xmlTextReaderPtr reader) {
    547     if ((reader == NULL) || (reader->ctxt == NULL)) {
    548 	fprintf(stderr, "xmlTextReader NULL\n");
    549 	return;
    550     }
    551     fprintf(stderr, "xmlTextReader: state %d depth %d ",
    552 	    reader->state, reader->depth);
    553     if (reader->node == NULL) {
    554 	fprintf(stderr, "node = NULL\n");
    555     } else {
    556 	fprintf(stderr, "node %s\n", reader->node->name);
    557     }
    558     fprintf(stderr, "  input: base %d, cur %d, depth %d: ",
    559 	    reader->base, reader->cur, reader->ctxt->nodeNr);
    560     if (reader->input->buffer == NULL) {
    561 	fprintf(stderr, "buffer is NULL\n");
    562     } else {
    563 #ifdef LIBXML_DEBUG_ENABLED
    564 	xmlDebugDumpString(stderr,
    565 		&reader->input->buffer->content[reader->cur]);
    566 #endif
    567 	fprintf(stderr, "\n");
    568     }
    569 }
    570 #endif
    571 
    572 /**
    573  * xmlTextReaderEntPush:
    574  * @reader:  the xmlTextReaderPtr used
    575  * @value:  the entity reference node
    576  *
    577  * Pushes a new entity reference node on top of the entities stack
    578  *
    579  * Returns 0 in case of error, the index in the stack otherwise
    580  */
    581 static int
    582 xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
    583 {
    584     if (reader->entMax <= 0) {
    585 	reader->entMax = 10;
    586 	reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
    587 		                                  sizeof(reader->entTab[0]));
    588         if (reader->entTab == NULL) {
    589             xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
    590             return (0);
    591         }
    592     }
    593     if (reader->entNr >= reader->entMax) {
    594         reader->entMax *= 2;
    595         reader->entTab =
    596             (xmlNodePtr *) xmlRealloc(reader->entTab,
    597                                       reader->entMax *
    598                                       sizeof(reader->entTab[0]));
    599         if (reader->entTab == NULL) {
    600             xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
    601             return (0);
    602         }
    603     }
    604     reader->entTab[reader->entNr] = value;
    605     reader->ent = value;
    606     return (reader->entNr++);
    607 }
    608 
    609 /**
    610  * xmlTextReaderEntPop:
    611  * @reader:  the xmlTextReaderPtr used
    612  *
    613  * Pops the top element entity from the entities stack
    614  *
    615  * Returns the entity just removed
    616  */
    617 static xmlNodePtr
    618 xmlTextReaderEntPop(xmlTextReaderPtr reader)
    619 {
    620     xmlNodePtr ret;
    621 
    622     if (reader->entNr <= 0)
    623         return (NULL);
    624     reader->entNr--;
    625     if (reader->entNr > 0)
    626         reader->ent = reader->entTab[reader->entNr - 1];
    627     else
    628         reader->ent = NULL;
    629     ret = reader->entTab[reader->entNr];
    630     reader->entTab[reader->entNr] = NULL;
    631     return (ret);
    632 }
    633 
    634 /**
    635  * xmlTextReaderStartElement:
    636  * @ctx: the user data (XML parser context)
    637  * @fullname:  The element name, including namespace prefix
    638  * @atts:  An array of name/value attributes pairs, NULL terminated
    639  *
    640  * called when an opening tag has been processed.
    641  */
    642 static void
    643 xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
    644 	                  const xmlChar **atts) {
    645     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    646     xmlTextReaderPtr reader = ctxt->_private;
    647 
    648 #ifdef DEBUG_CALLBACKS
    649     printf("xmlTextReaderStartElement(%s)\n", fullname);
    650 #endif
    651     if ((reader != NULL) && (reader->startElement != NULL)) {
    652 	reader->startElement(ctx, fullname, atts);
    653 	if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
    654 	    (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
    655 	    (ctxt->input->cur[1] == '>'))
    656 	    ctxt->node->extra = NODE_IS_EMPTY;
    657     }
    658     if (reader != NULL)
    659 	reader->state = XML_TEXTREADER_ELEMENT;
    660 }
    661 
    662 /**
    663  * xmlTextReaderEndElement:
    664  * @ctx: the user data (XML parser context)
    665  * @fullname:  The element name, including namespace prefix
    666  *
    667  * called when an ending tag has been processed.
    668  */
    669 static void
    670 xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
    671     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    672     xmlTextReaderPtr reader = ctxt->_private;
    673 
    674 #ifdef DEBUG_CALLBACKS
    675     printf("xmlTextReaderEndElement(%s)\n", fullname);
    676 #endif
    677     if ((reader != NULL) && (reader->endElement != NULL)) {
    678 	reader->endElement(ctx, fullname);
    679     }
    680 }
    681 
    682 /**
    683  * xmlTextReaderStartElementNs:
    684  * @ctx: the user data (XML parser context)
    685  * @localname:  the local name of the element
    686  * @prefix:  the element namespace prefix if available
    687  * @URI:  the element namespace name if available
    688  * @nb_namespaces:  number of namespace definitions on that node
    689  * @namespaces:  pointer to the array of prefix/URI pairs namespace definitions
    690  * @nb_attributes:  the number of attributes on that node
    691  * nb_defaulted:  the number of defaulted attributes.
    692  * @attributes:  pointer to the array of (localname/prefix/URI/value/end)
    693  *               attribute values.
    694  *
    695  * called when an opening tag has been processed.
    696  */
    697 static void
    698 xmlTextReaderStartElementNs(void *ctx,
    699                       const xmlChar *localname,
    700 		      const xmlChar *prefix,
    701 		      const xmlChar *URI,
    702 		      int nb_namespaces,
    703 		      const xmlChar **namespaces,
    704 		      int nb_attributes,
    705 		      int nb_defaulted,
    706 		      const xmlChar **attributes)
    707 {
    708     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    709     xmlTextReaderPtr reader = ctxt->_private;
    710 
    711 #ifdef DEBUG_CALLBACKS
    712     printf("xmlTextReaderStartElementNs(%s)\n", localname);
    713 #endif
    714     if ((reader != NULL) && (reader->startElementNs != NULL)) {
    715 	reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
    716 	                       namespaces, nb_attributes, nb_defaulted,
    717 			       attributes);
    718 	if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
    719 	    (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
    720 	    (ctxt->input->cur[1] == '>'))
    721 	    ctxt->node->extra = NODE_IS_EMPTY;
    722     }
    723     if (reader != NULL)
    724 	reader->state = XML_TEXTREADER_ELEMENT;
    725 }
    726 
    727 /**
    728  * xmlTextReaderEndElementNs:
    729  * @ctx: the user data (XML parser context)
    730  * @localname:  the local name of the element
    731  * @prefix:  the element namespace prefix if available
    732  * @URI:  the element namespace name if available
    733  *
    734  * called when an ending tag has been processed.
    735  */
    736 static void
    737 xmlTextReaderEndElementNs(void *ctx,
    738                           const xmlChar * localname,
    739                           const xmlChar * prefix,
    740 		          const xmlChar * URI)
    741 {
    742     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    743     xmlTextReaderPtr reader = ctxt->_private;
    744 
    745 #ifdef DEBUG_CALLBACKS
    746     printf("xmlTextReaderEndElementNs(%s)\n", localname);
    747 #endif
    748     if ((reader != NULL) && (reader->endElementNs != NULL)) {
    749 	reader->endElementNs(ctx, localname, prefix, URI);
    750     }
    751 }
    752 
    753 
    754 /**
    755  * xmlTextReaderCharacters:
    756  * @ctx: the user data (XML parser context)
    757  * @ch:  a xmlChar string
    758  * @len: the number of xmlChar
    759  *
    760  * receiving some chars from the parser.
    761  */
    762 static void
    763 xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
    764 {
    765     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    766     xmlTextReaderPtr reader = ctxt->_private;
    767 
    768 #ifdef DEBUG_CALLBACKS
    769     printf("xmlTextReaderCharacters()\n");
    770 #endif
    771     if ((reader != NULL) && (reader->characters != NULL)) {
    772 	reader->characters(ctx, ch, len);
    773     }
    774 }
    775 
    776 /**
    777  * xmlTextReaderCDataBlock:
    778  * @ctx: the user data (XML parser context)
    779  * @value:  The pcdata content
    780  * @len:  the block length
    781  *
    782  * called when a pcdata block has been parsed
    783  */
    784 static void
    785 xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
    786 {
    787     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    788     xmlTextReaderPtr reader = ctxt->_private;
    789 
    790 #ifdef DEBUG_CALLBACKS
    791     printf("xmlTextReaderCDataBlock()\n");
    792 #endif
    793     if ((reader != NULL) && (reader->cdataBlock != NULL)) {
    794 	reader->cdataBlock(ctx, ch, len);
    795     }
    796 }
    797 
    798 /**
    799  * xmlTextReaderPushData:
    800  * @reader:  the xmlTextReaderPtr used
    801  *
    802  * Push data down the progressive parser until a significant callback
    803  * got raised.
    804  *
    805  * Returns -1 in case of failure, 0 otherwise
    806  */
    807 static int
    808 xmlTextReaderPushData(xmlTextReaderPtr reader) {
    809     xmlBufferPtr inbuf;
    810     int val, s;
    811     xmlTextReaderState oldstate;
    812 
    813     if ((reader->input == NULL) || (reader->input->buffer == NULL))
    814 	return(-1);
    815 
    816     oldstate = reader->state;
    817     reader->state = XML_TEXTREADER_NONE;
    818     inbuf = reader->input->buffer;
    819 
    820     while (reader->state == XML_TEXTREADER_NONE) {
    821 	if (inbuf->use < reader->cur + CHUNK_SIZE) {
    822 	    /*
    823 	     * Refill the buffer unless we are at the end of the stream
    824 	     */
    825 	    if (reader->mode != XML_TEXTREADER_MODE_EOF) {
    826 		val = xmlParserInputBufferRead(reader->input, 4096);
    827 		if ((val == 0) &&
    828 		    (inbuf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
    829 		    if (inbuf->use == reader->cur) {
    830 			reader->mode = XML_TEXTREADER_MODE_EOF;
    831 			reader->state = oldstate;
    832 		    }
    833 		} else if (val < 0) {
    834 		    reader->mode = XML_TEXTREADER_MODE_EOF;
    835 		    reader->state = oldstate;
    836 		    if ((oldstate != XML_TEXTREADER_START) ||
    837 			(reader->ctxt->myDoc != NULL))
    838 			return(val);
    839 		} else if (val == 0) {
    840 		    /* mark the end of the stream and process the remains */
    841 		    reader->mode = XML_TEXTREADER_MODE_EOF;
    842 		    break;
    843 		}
    844 
    845 	    } else
    846 		break;
    847 	}
    848 	/*
    849 	 * parse by block of CHUNK_SIZE bytes, various tests show that
    850 	 * it's the best tradeoff at least on a 1.2GH Duron
    851 	 */
    852 	if (inbuf->use >= reader->cur + CHUNK_SIZE) {
    853 	    val = xmlParseChunk(reader->ctxt,
    854 		          (const char *) &inbuf->content[reader->cur],
    855 			  CHUNK_SIZE, 0);
    856 	    reader->cur += CHUNK_SIZE;
    857 	    if ((val != 0) || (reader->ctxt->wellFormed == 0))
    858 		return(-1);
    859 	} else {
    860 	    s = inbuf->use - reader->cur;
    861 	    val = xmlParseChunk(reader->ctxt,
    862 		          (const char *) &inbuf->content[reader->cur],
    863 			  s, 0);
    864 	    reader->cur += s;
    865 	    if ((val != 0) || (reader->ctxt->wellFormed == 0))
    866 		return(-1);
    867 	    break;
    868 	}
    869     }
    870 
    871     /*
    872      * Discard the consumed input when needed and possible
    873      */
    874     if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
    875         if (inbuf->alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
    876 	    if ((reader->cur >= 4096) &&
    877 		(inbuf->use - reader->cur <= CHUNK_SIZE)) {
    878 		val = xmlBufferShrink(inbuf, reader->cur);
    879 		if (val >= 0) {
    880 		    reader->cur -= val;
    881 		}
    882 	    }
    883 	}
    884     }
    885 
    886     /*
    887      * At the end of the stream signal that the work is done to the Push
    888      * parser.
    889      */
    890     else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
    891 	if (reader->state != XML_TEXTREADER_DONE) {
    892 	    s = inbuf->use - reader->cur;
    893 	    val = xmlParseChunk(reader->ctxt,
    894 		    (const char *) &inbuf->content[reader->cur],
    895 		    s, 1);
    896 	    reader->cur = inbuf->use;
    897 	    reader->state  = XML_TEXTREADER_DONE;
    898 	    if ((val != 0) || (reader->ctxt->wellFormed == 0))
    899 	        return(-1);
    900 	}
    901     }
    902     reader->state = oldstate;
    903     return(0);
    904 }
    905 
    906 #ifdef LIBXML_REGEXP_ENABLED
    907 /**
    908  * xmlTextReaderValidatePush:
    909  * @reader:  the xmlTextReaderPtr used
    910  *
    911  * Push the current node for validation
    912  */
    913 static void
    914 xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
    915     xmlNodePtr node = reader->node;
    916 
    917 #ifdef LIBXML_VALID_ENABLED
    918     if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
    919         (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
    920 	if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
    921 	    reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
    922 				    reader->ctxt->myDoc, node, node->name);
    923 	} else {
    924 	    /* TODO use the BuildQName interface */
    925 	    xmlChar *qname;
    926 
    927 	    qname = xmlStrdup(node->ns->prefix);
    928 	    qname = xmlStrcat(qname, BAD_CAST ":");
    929 	    qname = xmlStrcat(qname, node->name);
    930 	    reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
    931 				    reader->ctxt->myDoc, node, qname);
    932 	    if (qname != NULL)
    933 		xmlFree(qname);
    934 	}
    935     }
    936 #endif /* LIBXML_VALID_ENABLED */
    937 #ifdef LIBXML_SCHEMAS_ENABLED
    938     if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
    939                (reader->rngValidCtxt != NULL)) {
    940 	int ret;
    941 
    942 	if (reader->rngFullNode != NULL) return;
    943 	ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
    944 	                                    reader->ctxt->myDoc,
    945 					    node);
    946 	if (ret == 0) {
    947 	    /*
    948 	     * this element requires a full tree
    949 	     */
    950 	    node = xmlTextReaderExpand(reader);
    951 	    if (node == NULL) {
    952 printf("Expand failed !\n");
    953 	        ret = -1;
    954 	    } else {
    955 		ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
    956 						    reader->ctxt->myDoc,
    957 						    node);
    958 		reader->rngFullNode = node;
    959 	    }
    960 	}
    961 	if (ret != 1)
    962 	    reader->rngValidErrors++;
    963     }
    964 #endif
    965 }
    966 
    967 /**
    968  * xmlTextReaderValidateCData:
    969  * @reader:  the xmlTextReaderPtr used
    970  * @data:  pointer to the CData
    971  * @len:  lenght of the CData block in bytes.
    972  *
    973  * Push some CData for validation
    974  */
    975 static void
    976 xmlTextReaderValidateCData(xmlTextReaderPtr reader,
    977                            const xmlChar *data, int len) {
    978 #ifdef LIBXML_VALID_ENABLED
    979     if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
    980         (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
    981 	reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
    982 	                                            data, len);
    983     }
    984 #endif /* LIBXML_VALID_ENABLED */
    985 #ifdef LIBXML_SCHEMAS_ENABLED
    986     if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
    987                (reader->rngValidCtxt != NULL)) {
    988 	int ret;
    989 
    990 	if (reader->rngFullNode != NULL) return;
    991 	ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
    992 	if (ret != 1)
    993 	    reader->rngValidErrors++;
    994     }
    995 #endif
    996 }
    997 
    998 /**
    999  * xmlTextReaderValidatePop:
   1000  * @reader:  the xmlTextReaderPtr used
   1001  *
   1002  * Pop the current node from validation
   1003  */
   1004 static void
   1005 xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
   1006     xmlNodePtr node = reader->node;
   1007 
   1008 #ifdef LIBXML_VALID_ENABLED
   1009     if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
   1010         (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
   1011 	if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
   1012 	    reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
   1013 				    reader->ctxt->myDoc, node, node->name);
   1014 	} else {
   1015 	    /* TODO use the BuildQName interface */
   1016 	    xmlChar *qname;
   1017 
   1018 	    qname = xmlStrdup(node->ns->prefix);
   1019 	    qname = xmlStrcat(qname, BAD_CAST ":");
   1020 	    qname = xmlStrcat(qname, node->name);
   1021 	    reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
   1022 				    reader->ctxt->myDoc, node, qname);
   1023 	    if (qname != NULL)
   1024 		xmlFree(qname);
   1025 	}
   1026     }
   1027 #endif /* LIBXML_VALID_ENABLED */
   1028 #ifdef LIBXML_SCHEMAS_ENABLED
   1029     if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
   1030                (reader->rngValidCtxt != NULL)) {
   1031 	int ret;
   1032 
   1033 	if (reader->rngFullNode != NULL) {
   1034 	    if (node == reader->rngFullNode)
   1035 	        reader->rngFullNode = NULL;
   1036 	    return;
   1037 	}
   1038 	ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
   1039 	                                   reader->ctxt->myDoc,
   1040 					   node);
   1041 	if (ret != 1)
   1042 	    reader->rngValidErrors++;
   1043     }
   1044 #endif
   1045 }
   1046 
   1047 /**
   1048  * xmlTextReaderValidateEntity:
   1049  * @reader:  the xmlTextReaderPtr used
   1050  *
   1051  * Handle the validation when an entity reference is encountered and
   1052  * entity substitution is not activated. As a result the parser interface
   1053  * must walk through the entity and do the validation calls
   1054  */
   1055 static void
   1056 xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
   1057     xmlNodePtr oldnode = reader->node;
   1058     xmlNodePtr node = reader->node;
   1059     xmlParserCtxtPtr ctxt = reader->ctxt;
   1060 
   1061     do {
   1062 	if (node->type == XML_ENTITY_REF_NODE) {
   1063 	    /*
   1064 	     * Case where the underlying tree is not availble, lookup the entity
   1065 	     * and walk it.
   1066 	     */
   1067 	    if ((node->children == NULL) && (ctxt->sax != NULL) &&
   1068 		(ctxt->sax->getEntity != NULL)) {
   1069 		node->children = (xmlNodePtr)
   1070 		    ctxt->sax->getEntity(ctxt, node->name);
   1071 	    }
   1072 
   1073 	    if ((node->children != NULL) &&
   1074 		(node->children->type == XML_ENTITY_DECL) &&
   1075 		(node->children->children != NULL)) {
   1076 		xmlTextReaderEntPush(reader, node);
   1077 		node = node->children->children;
   1078 		continue;
   1079 	    } else {
   1080 		/*
   1081 		 * The error has probably be raised already.
   1082 		 */
   1083 		if (node == oldnode)
   1084 		    break;
   1085 		node = node->next;
   1086 	    }
   1087 #ifdef LIBXML_REGEXP_ENABLED
   1088 	} else if (node->type == XML_ELEMENT_NODE) {
   1089 	    reader->node = node;
   1090 	    xmlTextReaderValidatePush(reader);
   1091 	} else if ((node->type == XML_TEXT_NODE) ||
   1092 		   (node->type == XML_CDATA_SECTION_NODE)) {
   1093             xmlTextReaderValidateCData(reader, node->content,
   1094 	                               xmlStrlen(node->content));
   1095 #endif
   1096 	}
   1097 
   1098 	/*
   1099 	 * go to next node
   1100 	 */
   1101 	if (node->children != NULL) {
   1102 	    node = node->children;
   1103 	    continue;
   1104 	} else if (node->type == XML_ELEMENT_NODE) {
   1105 	    xmlTextReaderValidatePop(reader);
   1106 	}
   1107 	if (node->next != NULL) {
   1108 	    node = node->next;
   1109 	    continue;
   1110 	}
   1111 	do {
   1112 	    node = node->parent;
   1113 	    if (node->type == XML_ELEMENT_NODE) {
   1114 	        xmlNodePtr tmp;
   1115 		if (reader->entNr == 0) {
   1116 		    while ((tmp = node->last) != NULL) {
   1117 			if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
   1118 			    xmlUnlinkNode(tmp);
   1119 			    xmlTextReaderFreeNode(reader, tmp);
   1120 			} else
   1121 			    break;
   1122 		    }
   1123 		}
   1124 		reader->node = node;
   1125 		xmlTextReaderValidatePop(reader);
   1126 	    }
   1127 	    if ((node->type == XML_ENTITY_DECL) &&
   1128 		(reader->ent != NULL) && (reader->ent->children == node)) {
   1129 		node = xmlTextReaderEntPop(reader);
   1130 	    }
   1131 	    if (node == oldnode)
   1132 		break;
   1133 	    if (node->next != NULL) {
   1134 		node = node->next;
   1135 		break;
   1136 	    }
   1137 	} while ((node != NULL) && (node != oldnode));
   1138     } while ((node != NULL) && (node != oldnode));
   1139     reader->node = oldnode;
   1140 }
   1141 #endif /* LIBXML_REGEXP_ENABLED */
   1142 
   1143 
   1144 /**
   1145  * xmlTextReaderGetSuccessor:
   1146  * @cur:  the current node
   1147  *
   1148  * Get the successor of a node if available.
   1149  *
   1150  * Returns the successor node or NULL
   1151  */
   1152 static xmlNodePtr
   1153 xmlTextReaderGetSuccessor(xmlNodePtr cur) {
   1154     if (cur == NULL) return(NULL) ; /* ERROR */
   1155     if (cur->next != NULL) return(cur->next) ;
   1156     do {
   1157         cur = cur->parent;
   1158         if (cur == NULL) break;
   1159         if (cur->next != NULL) return(cur->next);
   1160     } while (cur != NULL);
   1161     return(cur);
   1162 }
   1163 
   1164 /**
   1165  * xmlTextReaderDoExpand:
   1166  * @reader:  the xmlTextReaderPtr used
   1167  *
   1168  * Makes sure that the current node is fully read as well as all its
   1169  * descendant. It means the full DOM subtree must be available at the
   1170  * end of the call.
   1171  *
   1172  * Returns 1 if the node was expanded successfully, 0 if there is no more
   1173  *          nodes to read, or -1 in case of error
   1174  */
   1175 static int
   1176 xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
   1177     int val;
   1178 
   1179     if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
   1180         return(-1);
   1181     do {
   1182 	if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
   1183 
   1184         if (xmlTextReaderGetSuccessor(reader->node) != NULL)
   1185 	    return(1);
   1186 	if (reader->ctxt->nodeNr < reader->depth)
   1187 	    return(1);
   1188 	if (reader->mode == XML_TEXTREADER_MODE_EOF)
   1189 	    return(1);
   1190 	val = xmlTextReaderPushData(reader);
   1191 	if (val < 0){
   1192 	    reader->mode = XML_TEXTREADER_MODE_ERROR;
   1193 	    return(-1);
   1194 	}
   1195     } while(reader->mode != XML_TEXTREADER_MODE_EOF);
   1196     return(1);
   1197 }
   1198 
   1199 /**
   1200  * xmlTextReaderCollectSiblings:
   1201  * @node:    the first child
   1202  *
   1203  *  Traverse depth-first through all sibling nodes and their children
   1204  *  nodes and concatenate their content. This is an auxiliary function
   1205  *  to xmlTextReaderReadString.
   1206  *
   1207  *  Returns a string containing the content, or NULL in case of error.
   1208  */
   1209 static xmlChar *
   1210 xmlTextReaderCollectSiblings(xmlNodePtr node)
   1211 {
   1212     xmlBufferPtr buffer;
   1213     xmlChar *ret;
   1214 
   1215     buffer = xmlBufferCreate();
   1216     if (buffer == NULL)
   1217        return NULL;
   1218 
   1219     for ( ; node != NULL; node = node->next) {
   1220        switch (node->type) {
   1221        case XML_TEXT_NODE:
   1222        case XML_CDATA_SECTION_NODE:
   1223            xmlBufferCat(buffer, node->content);
   1224            break;
   1225        case XML_ELEMENT_NODE: {
   1226            xmlChar *tmp;
   1227 
   1228 	   tmp = xmlTextReaderCollectSiblings(node->children);
   1229            xmlBufferCat(buffer, tmp);
   1230 	   xmlFree(tmp);
   1231 	   break;
   1232        }
   1233        default:
   1234            break;
   1235        }
   1236     }
   1237     ret = buffer->content;
   1238     buffer->content = NULL;
   1239     xmlBufferFree(buffer);
   1240     return(ret);
   1241 }
   1242 
   1243 /**
   1244  * xmlTextReaderRead:
   1245  * @reader:  the xmlTextReaderPtr used
   1246  *
   1247  *  Moves the position of the current instance to the next node in
   1248  *  the stream, exposing its properties.
   1249  *
   1250  *  Returns 1 if the node was read successfully, 0 if there is no more
   1251  *          nodes to read, or -1 in case of error
   1252  */
   1253 int
   1254 xmlTextReaderRead(xmlTextReaderPtr reader) {
   1255     int val, olddepth = 0;
   1256     xmlTextReaderState oldstate = XML_TEXTREADER_START;
   1257     xmlNodePtr oldnode = NULL;
   1258 
   1259 
   1260     if (reader == NULL)
   1261 	return(-1);
   1262     reader->curnode = NULL;
   1263     if (reader->doc != NULL)
   1264         return(xmlTextReaderReadTree(reader));
   1265     if (reader->ctxt == NULL)
   1266 	return(-1);
   1267     if (reader->ctxt->wellFormed != 1)
   1268 	return(-1);
   1269 
   1270 #ifdef DEBUG_READER
   1271     fprintf(stderr, "\nREAD ");
   1272     DUMP_READER
   1273 #endif
   1274     if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
   1275 	reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
   1276 	/*
   1277 	 * Initial state
   1278 	 */
   1279 	do {
   1280 	    val = xmlTextReaderPushData(reader);
   1281 		if (val < 0){
   1282 			reader->mode = XML_TEXTREADER_MODE_ERROR;
   1283 			reader->state = XML_TEXTREADER_ERROR;
   1284 		return(-1);
   1285 		}
   1286 	} while ((reader->ctxt->node == NULL) &&
   1287 		 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
   1288 		  (reader->state != XML_TEXTREADER_DONE)));
   1289 	if (reader->ctxt->node == NULL) {
   1290 	    if (reader->ctxt->myDoc != NULL) {
   1291 		reader->node = reader->ctxt->myDoc->children;
   1292 	    }
   1293 	    if (reader->node == NULL){
   1294 			reader->mode = XML_TEXTREADER_MODE_ERROR;
   1295 			reader->state = XML_TEXTREADER_ERROR;
   1296 		return(-1);
   1297 		}
   1298 	    reader->state = XML_TEXTREADER_ELEMENT;
   1299 	} else {
   1300 	    if (reader->ctxt->myDoc != NULL) {
   1301 		reader->node = reader->ctxt->myDoc->children;
   1302 	    }
   1303 	    if (reader->node == NULL)
   1304 		reader->node = reader->ctxt->nodeTab[0];
   1305 	    reader->state = XML_TEXTREADER_ELEMENT;
   1306 	}
   1307 	reader->depth = 0;
   1308 	reader->ctxt->parseMode = XML_PARSE_READER;
   1309 	goto node_found;
   1310     }
   1311     oldstate = reader->state;
   1312     olddepth = reader->ctxt->nodeNr;
   1313     oldnode = reader->node;
   1314 
   1315 get_next_node:
   1316     if (reader->node == NULL) {
   1317 	if (reader->mode == XML_TEXTREADER_MODE_EOF)
   1318 	    return(0);
   1319 	else
   1320 	    return(-1);
   1321     }
   1322 
   1323     /*
   1324      * If we are not backtracking on ancestors or examined nodes,
   1325      * that the parser didn't finished or that we arent at the end
   1326      * of stream, continue processing.
   1327      */
   1328     while ((reader->node != NULL) && (reader->node->next == NULL) &&
   1329 	   (reader->ctxt->nodeNr == olddepth) &&
   1330            ((oldstate == XML_TEXTREADER_BACKTRACK) ||
   1331             (reader->node->children == NULL) ||
   1332 	    (reader->node->type == XML_ENTITY_REF_NODE) ||
   1333 	    ((reader->node->children != NULL) &&
   1334 	     (reader->node->children->type == XML_TEXT_NODE) &&
   1335 	     (reader->node->children->next == NULL)) ||
   1336 	    (reader->node->type == XML_DTD_NODE) ||
   1337 	    (reader->node->type == XML_DOCUMENT_NODE) ||
   1338 	    (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
   1339 	   ((reader->ctxt->node == NULL) ||
   1340 	    (reader->ctxt->node == reader->node) ||
   1341 	    (reader->ctxt->node == reader->node->parent)) &&
   1342 	   (reader->ctxt->instate != XML_PARSER_EOF)) {
   1343 	val = xmlTextReaderPushData(reader);
   1344 	if (val < 0){
   1345 		reader->mode = XML_TEXTREADER_MODE_ERROR;
   1346 		reader->state = XML_TEXTREADER_ERROR;
   1347 	    return(-1);
   1348 	}
   1349 	if (reader->node == NULL)
   1350 	    goto node_end;
   1351     }
   1352     if (oldstate != XML_TEXTREADER_BACKTRACK) {
   1353 	if ((reader->node->children != NULL) &&
   1354 	    (reader->node->type != XML_ENTITY_REF_NODE) &&
   1355 	    (reader->node->type != XML_XINCLUDE_START) &&
   1356 	    (reader->node->type != XML_DTD_NODE)) {
   1357 	    reader->node = reader->node->children;
   1358 	    reader->depth++;
   1359 	    reader->state = XML_TEXTREADER_ELEMENT;
   1360 	    goto node_found;
   1361 	}
   1362     }
   1363     if (reader->node->next != NULL) {
   1364 	if ((oldstate == XML_TEXTREADER_ELEMENT) &&
   1365             (reader->node->type == XML_ELEMENT_NODE) &&
   1366 	    (reader->node->children == NULL) &&
   1367 	    ((reader->node->extra & NODE_IS_EMPTY) == 0)
   1368 #ifdef LIBXML_XINCLUDE_ENABLED
   1369 	    && (reader->in_xinclude <= 0)
   1370 #endif
   1371 	    ) {
   1372 	    reader->state = XML_TEXTREADER_END;
   1373 	    goto node_found;
   1374 	}
   1375 #ifdef LIBXML_REGEXP_ENABLED
   1376 	if ((reader->validate) &&
   1377 	    (reader->node->type == XML_ELEMENT_NODE))
   1378 	    xmlTextReaderValidatePop(reader);
   1379 #endif /* LIBXML_REGEXP_ENABLED */
   1380         if ((reader->preserves > 0) &&
   1381 	    (reader->node->extra & NODE_IS_SPRESERVED))
   1382 	    reader->preserves--;
   1383 	reader->node = reader->node->next;
   1384 	reader->state = XML_TEXTREADER_ELEMENT;
   1385 
   1386 	/*
   1387 	 * Cleanup of the old node
   1388 	 */
   1389 	if ((reader->preserves == 0) &&
   1390 #ifdef LIBXML_XINCLUDE_ENABLED
   1391 	    (reader->in_xinclude == 0) &&
   1392 #endif
   1393 	    (reader->entNr == 0) &&
   1394 	    (reader->node->prev != NULL) &&
   1395 	    (reader->node->prev->type != XML_DTD_NODE)) {
   1396 	    xmlNodePtr tmp = reader->node->prev;
   1397 	    if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
   1398 		xmlUnlinkNode(tmp);
   1399 		xmlTextReaderFreeNode(reader, tmp);
   1400 	    }
   1401 	}
   1402 
   1403 	goto node_found;
   1404     }
   1405     if ((oldstate == XML_TEXTREADER_ELEMENT) &&
   1406 	(reader->node->type == XML_ELEMENT_NODE) &&
   1407 	(reader->node->children == NULL) &&
   1408 	((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
   1409 	reader->state = XML_TEXTREADER_END;
   1410 	goto node_found;
   1411     }
   1412 #ifdef LIBXML_REGEXP_ENABLED
   1413     if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
   1414 	xmlTextReaderValidatePop(reader);
   1415 #endif /* LIBXML_REGEXP_ENABLED */
   1416     if ((reader->preserves > 0) &&
   1417 	(reader->node->extra & NODE_IS_SPRESERVED))
   1418 	reader->preserves--;
   1419     reader->node = reader->node->parent;
   1420     if ((reader->node == NULL) ||
   1421 	(reader->node->type == XML_DOCUMENT_NODE) ||
   1422 #ifdef LIBXML_DOCB_ENABLED
   1423 	(reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
   1424 #endif
   1425 	(reader->node->type == XML_HTML_DOCUMENT_NODE)) {
   1426 	if (reader->mode != XML_TEXTREADER_MODE_EOF) {
   1427 	    val = xmlParseChunk(reader->ctxt, "", 0, 1);
   1428 	    reader->state = XML_TEXTREADER_DONE;
   1429 	    if (val != 0)
   1430 	        return(-1);
   1431 	}
   1432 	reader->node = NULL;
   1433 	reader->depth = -1;
   1434 
   1435 	/*
   1436 	 * Cleanup of the old node
   1437 	 */
   1438 	if ((oldnode != NULL) && (reader->preserves == 0) &&
   1439 #ifdef LIBXML_XINCLUDE_ENABLED
   1440 	    (reader->in_xinclude == 0) &&
   1441 #endif
   1442 	    (reader->entNr == 0) &&
   1443 	    (oldnode->type != XML_DTD_NODE) &&
   1444 	    ((oldnode->extra & NODE_IS_PRESERVED) == 0)) {
   1445 	    xmlUnlinkNode(oldnode);
   1446 	    xmlTextReaderFreeNode(reader, oldnode);
   1447 	}
   1448 
   1449 	goto node_end;
   1450     }
   1451     if ((reader->preserves == 0) &&
   1452 #ifdef LIBXML_XINCLUDE_ENABLED
   1453         (reader->in_xinclude == 0) &&
   1454 #endif
   1455 	(reader->entNr == 0) &&
   1456         (reader->node->last != NULL) &&
   1457         ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
   1458 	xmlNodePtr tmp = reader->node->last;
   1459 	xmlUnlinkNode(tmp);
   1460 	xmlTextReaderFreeNode(reader, tmp);
   1461     }
   1462     reader->depth--;
   1463     reader->state = XML_TEXTREADER_BACKTRACK;
   1464 
   1465 node_found:
   1466     DUMP_READER
   1467 
   1468     /*
   1469      * If we are in the middle of a piece of CDATA make sure it's finished
   1470      */
   1471     if ((reader->node != NULL) &&
   1472         (reader->node->next == NULL) &&
   1473         ((reader->node->type == XML_TEXT_NODE) ||
   1474 	 (reader->node->type == XML_CDATA_SECTION_NODE))) {
   1475             if (xmlTextReaderExpand(reader) == NULL)
   1476 	        return -1;
   1477     }
   1478 
   1479 #ifdef LIBXML_XINCLUDE_ENABLED
   1480     /*
   1481      * Handle XInclude if asked for
   1482      */
   1483     if ((reader->xinclude) && (reader->node != NULL) &&
   1484 	(reader->node->type == XML_ELEMENT_NODE) &&
   1485 	(reader->node->ns != NULL) &&
   1486 	((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
   1487 	 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
   1488 	if (reader->xincctxt == NULL) {
   1489 	    reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
   1490 	    xmlXIncludeSetFlags(reader->xincctxt,
   1491 	                        reader->parserFlags & (~XML_PARSE_NOXINCNODE));
   1492 	}
   1493 	/*
   1494 	 * expand that node and process it
   1495 	 */
   1496 	if (xmlTextReaderExpand(reader) == NULL)
   1497 	    return -1;
   1498 	xmlXIncludeProcessNode(reader->xincctxt, reader->node);
   1499     }
   1500     if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_START)) {
   1501         reader->in_xinclude++;
   1502 	goto get_next_node;
   1503     }
   1504     if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_END)) {
   1505         reader->in_xinclude--;
   1506 	goto get_next_node;
   1507     }
   1508 #endif
   1509     /*
   1510      * Handle entities enter and exit when in entity replacement mode
   1511      */
   1512     if ((reader->node != NULL) &&
   1513 	(reader->node->type == XML_ENTITY_REF_NODE) &&
   1514 	(reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
   1515 	/*
   1516 	 * Case where the underlying tree is not availble, lookup the entity
   1517 	 * and walk it.
   1518 	 */
   1519 	if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
   1520 	    (reader->ctxt->sax->getEntity != NULL)) {
   1521 	    reader->node->children = (xmlNodePtr)
   1522 		reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
   1523 	}
   1524 
   1525 	if ((reader->node->children != NULL) &&
   1526 	    (reader->node->children->type == XML_ENTITY_DECL) &&
   1527 	    (reader->node->children->children != NULL)) {
   1528 	    xmlTextReaderEntPush(reader, reader->node);
   1529 	    reader->node = reader->node->children->children;
   1530 	}
   1531 #ifdef LIBXML_REGEXP_ENABLED
   1532     } else if ((reader->node != NULL) &&
   1533 	       (reader->node->type == XML_ENTITY_REF_NODE) &&
   1534 	       (reader->ctxt != NULL) && (reader->validate)) {
   1535 	xmlTextReaderValidateEntity(reader);
   1536 #endif /* LIBXML_REGEXP_ENABLED */
   1537     }
   1538     if ((reader->node != NULL) &&
   1539 	(reader->node->type == XML_ENTITY_DECL) &&
   1540 	(reader->ent != NULL) && (reader->ent->children == reader->node)) {
   1541 	reader->node = xmlTextReaderEntPop(reader);
   1542 	reader->depth++;
   1543         goto get_next_node;
   1544     }
   1545 #ifdef LIBXML_REGEXP_ENABLED
   1546     if ((reader->validate) && (reader->node != NULL)) {
   1547 	xmlNodePtr node = reader->node;
   1548 
   1549 	if ((node->type == XML_ELEMENT_NODE) &&
   1550             ((reader->state != XML_TEXTREADER_END) &&
   1551 	     (reader->state != XML_TEXTREADER_BACKTRACK))) {
   1552 	    xmlTextReaderValidatePush(reader);
   1553 	} else if ((node->type == XML_TEXT_NODE) ||
   1554 		   (node->type == XML_CDATA_SECTION_NODE)) {
   1555             xmlTextReaderValidateCData(reader, node->content,
   1556 	                               xmlStrlen(node->content));
   1557 	}
   1558     }
   1559 #endif /* LIBXML_REGEXP_ENABLED */
   1560 #ifdef LIBXML_PATTERN_ENABLED
   1561     if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
   1562         (reader->state != XML_TEXTREADER_BACKTRACK)) {
   1563         int i;
   1564 	for (i = 0;i < reader->patternNr;i++) {
   1565 	     if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
   1566 	         xmlTextReaderPreserve(reader);
   1567 		 break;
   1568              }
   1569 	}
   1570     }
   1571 #endif /* LIBXML_PATTERN_ENABLED */
   1572 #ifdef LIBXML_SCHEMAS_ENABLED
   1573     if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) &&
   1574         (reader->xsdValidErrors == 0) &&
   1575 	(reader->xsdValidCtxt != NULL)) {
   1576 	reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt);
   1577     }
   1578 #endif /* LIBXML_PATTERN_ENABLED */
   1579     return(1);
   1580 node_end:
   1581     reader->state = XML_TEXTREADER_DONE;
   1582     return(0);
   1583 }
   1584 
   1585 /**
   1586  * xmlTextReaderReadState:
   1587  * @reader:  the xmlTextReaderPtr used
   1588  *
   1589  * Gets the read state of the reader.
   1590  *
   1591  * Returns the state value, or -1 in case of error
   1592  */
   1593 int
   1594 xmlTextReaderReadState(xmlTextReaderPtr reader) {
   1595     if (reader == NULL)
   1596 	return(-1);
   1597     return(reader->mode);
   1598 }
   1599 
   1600 /**
   1601  * xmlTextReaderExpand:
   1602  * @reader:  the xmlTextReaderPtr used
   1603  *
   1604  * Reads the contents of the current node and the full subtree. It then makes
   1605  * the subtree available until the next xmlTextReaderRead() call
   1606  *
   1607  * Returns a node pointer valid until the next xmlTextReaderRead() call
   1608  *         or NULL in case of error.
   1609  */
   1610 xmlNodePtr
   1611 xmlTextReaderExpand(xmlTextReaderPtr reader) {
   1612     if ((reader == NULL) || (reader->node == NULL))
   1613         return(NULL);
   1614     if (reader->doc != NULL)
   1615         return(reader->node);
   1616     if (reader->ctxt == NULL)
   1617         return(NULL);
   1618     if (xmlTextReaderDoExpand(reader) < 0)
   1619         return(NULL);
   1620     return(reader->node);
   1621 }
   1622 
   1623 /**
   1624  * xmlTextReaderNext:
   1625  * @reader:  the xmlTextReaderPtr used
   1626  *
   1627  * Skip to the node following the current one in document order while
   1628  * avoiding the subtree if any.
   1629  *
   1630  * Returns 1 if the node was read successfully, 0 if there is no more
   1631  *          nodes to read, or -1 in case of error
   1632  */
   1633 int
   1634 xmlTextReaderNext(xmlTextReaderPtr reader) {
   1635     int ret;
   1636     xmlNodePtr cur;
   1637 
   1638     if (reader == NULL)
   1639 	return(-1);
   1640     if (reader->doc != NULL)
   1641         return(xmlTextReaderNextTree(reader));
   1642     cur = reader->node;
   1643     if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
   1644         return(xmlTextReaderRead(reader));
   1645     if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
   1646         return(xmlTextReaderRead(reader));
   1647     if (cur->extra & NODE_IS_EMPTY)
   1648         return(xmlTextReaderRead(reader));
   1649     do {
   1650         ret = xmlTextReaderRead(reader);
   1651 	if (ret != 1)
   1652 	    return(ret);
   1653     } while (reader->node != cur);
   1654     return(xmlTextReaderRead(reader));
   1655 }
   1656 
   1657 #ifdef LIBXML_WRITER_ENABLED
   1658 /**
   1659  * xmlTextReaderReadInnerXml:
   1660  * @reader:  the xmlTextReaderPtr used
   1661  *
   1662  * Reads the contents of the current node, including child nodes and markup.
   1663  *
   1664  * Returns a string containing the XML content, or NULL if the current node
   1665  *         is neither an element nor attribute, or has no child nodes. The
   1666  *         string must be deallocated by the caller.
   1667  */
   1668 xmlChar *
   1669 xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
   1670 {
   1671     xmlChar *resbuf;
   1672     xmlNodePtr node, cur_node;
   1673     xmlBufferPtr buff, buff2;
   1674     xmlDocPtr doc;
   1675 
   1676     if (xmlTextReaderExpand(reader) == NULL) {
   1677         return NULL;
   1678     }
   1679     doc = reader->doc;
   1680     buff = xmlBufferCreate();
   1681     for (cur_node = reader->node->children; cur_node != NULL;
   1682          cur_node = cur_node->next) {
   1683         node = xmlDocCopyNode(cur_node, doc, 1);
   1684         buff2 = xmlBufferCreate();
   1685         if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
   1686             xmlFreeNode(node);
   1687             xmlBufferFree(buff2);
   1688             xmlBufferFree(buff);
   1689             return NULL;
   1690         }
   1691         xmlBufferCat(buff, buff2->content);
   1692         xmlFreeNode(node);
   1693         xmlBufferFree(buff2);
   1694     }
   1695     resbuf = buff->content;
   1696     buff->content = NULL;
   1697 
   1698     xmlBufferFree(buff);
   1699     return resbuf;
   1700 }
   1701 #endif
   1702 
   1703 #ifdef LIBXML_WRITER_ENABLED
   1704 /**
   1705  * xmlTextReaderReadOuterXml:
   1706  * @reader:  the xmlTextReaderPtr used
   1707  *
   1708  * Reads the contents of the current node, including child nodes and markup.
   1709  *
   1710  * Returns a string containing the XML content, or NULL if the current node
   1711  *         is neither an element nor attribute, or has no child nodes. The
   1712  *         string must be deallocated by the caller.
   1713  */
   1714 xmlChar *
   1715 xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
   1716 {
   1717     xmlChar *resbuf;
   1718     xmlNodePtr node;
   1719     xmlBufferPtr buff;
   1720     xmlDocPtr doc;
   1721 
   1722     node = reader->node;
   1723     doc = reader->doc;
   1724     if (xmlTextReaderExpand(reader) == NULL) {
   1725         return NULL;
   1726     }
   1727     node = xmlDocCopyNode(node, doc, 1);
   1728     buff = xmlBufferCreate();
   1729     if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
   1730         xmlFreeNode(node);
   1731         xmlBufferFree(buff);
   1732         return NULL;
   1733     }
   1734 
   1735     resbuf = buff->content;
   1736     buff->content = NULL;
   1737 
   1738     xmlFreeNode(node);
   1739     xmlBufferFree(buff);
   1740     return resbuf;
   1741 }
   1742 #endif
   1743 
   1744 /**
   1745  * xmlTextReaderReadString:
   1746  * @reader:  the xmlTextReaderPtr used
   1747  *
   1748  * Reads the contents of an element or a text node as a string.
   1749  *
   1750  * Returns a string containing the contents of the Element or Text node,
   1751  *         or NULL if the reader is positioned on any other type of node.
   1752  *         The string must be deallocated by the caller.
   1753  */
   1754 xmlChar *
   1755 xmlTextReaderReadString(xmlTextReaderPtr reader)
   1756 {
   1757     xmlNodePtr node;
   1758 
   1759     if ((reader == NULL) || (reader->node == NULL))
   1760        return(NULL);
   1761 
   1762     node = (reader->curnode != NULL) ? reader->curnode : reader->node;
   1763     switch (node->type) {
   1764     case XML_TEXT_NODE:
   1765        if (node->content != NULL)
   1766            return(xmlStrdup(node->content));
   1767        break;
   1768     case XML_ELEMENT_NODE:
   1769 	if (xmlTextReaderDoExpand(reader) != -1) {
   1770 	    return xmlTextReaderCollectSiblings(node->children);
   1771 	}
   1772     case XML_ATTRIBUTE_NODE:
   1773 	TODO
   1774 	break;
   1775     default:
   1776        break;
   1777     }
   1778     return(NULL);
   1779 }
   1780 
   1781 #if 0
   1782 /**
   1783  * xmlTextReaderReadBase64:
   1784  * @reader:  the xmlTextReaderPtr used
   1785  * @array:  a byte array to store the content.
   1786  * @offset:  the zero-based index into array where the method should
   1787  *           begin to write.
   1788  * @len:  the number of bytes to write.
   1789  *
   1790  * Reads and decodes the Base64 encoded contents of an element and
   1791  * stores the result in a byte buffer.
   1792  *
   1793  * Returns the number of bytes written to array, or zero if the current
   1794  *         instance is not positioned on an element or -1 in case of error.
   1795  */
   1796 int
   1797 xmlTextReaderReadBase64(xmlTextReaderPtr reader,
   1798                         unsigned char *array ATTRIBUTE_UNUSED,
   1799 	                int offset ATTRIBUTE_UNUSED,
   1800 			int len ATTRIBUTE_UNUSED) {
   1801     if ((reader == NULL) || (reader->ctxt == NULL))
   1802 	return(-1);
   1803     if (reader->ctxt->wellFormed != 1)
   1804 	return(-1);
   1805 
   1806     if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
   1807 	return(0);
   1808     TODO
   1809     return(0);
   1810 }
   1811 
   1812 /**
   1813  * xmlTextReaderReadBinHex:
   1814  * @reader:  the xmlTextReaderPtr used
   1815  * @array:  a byte array to store the content.
   1816  * @offset:  the zero-based index into array where the method should
   1817  *           begin to write.
   1818  * @len:  the number of bytes to write.
   1819  *
   1820  * Reads and decodes the BinHex encoded contents of an element and
   1821  * stores the result in a byte buffer.
   1822  *
   1823  * Returns the number of bytes written to array, or zero if the current
   1824  *         instance is not positioned on an element or -1 in case of error.
   1825  */
   1826 int
   1827 xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
   1828                         unsigned char *array ATTRIBUTE_UNUSED,
   1829 	                int offset ATTRIBUTE_UNUSED,
   1830 			int len ATTRIBUTE_UNUSED) {
   1831     if ((reader == NULL) || (reader->ctxt == NULL))
   1832 	return(-1);
   1833     if (reader->ctxt->wellFormed != 1)
   1834 	return(-1);
   1835 
   1836     if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
   1837 	return(0);
   1838     TODO
   1839     return(0);
   1840 }
   1841 #endif
   1842 
   1843 /************************************************************************
   1844  *									*
   1845  *			Operating on a preparsed tree			*
   1846  *									*
   1847  ************************************************************************/
   1848 static int
   1849 xmlTextReaderNextTree(xmlTextReaderPtr reader)
   1850 {
   1851     if (reader == NULL)
   1852         return(-1);
   1853 
   1854     if (reader->state == XML_TEXTREADER_END)
   1855         return(0);
   1856 
   1857     if (reader->node == NULL) {
   1858         if (reader->doc->children == NULL) {
   1859             reader->state = XML_TEXTREADER_END;
   1860             return(0);
   1861         }
   1862 
   1863         reader->node = reader->doc->children;
   1864         reader->state = XML_TEXTREADER_START;
   1865         return(1);
   1866     }
   1867 
   1868     if (reader->state != XML_TEXTREADER_BACKTRACK) {
   1869 	/* Here removed traversal to child, because we want to skip the subtree,
   1870 	replace with traversal to sibling to skip subtree */
   1871         if (reader->node->next != 0) {
   1872 	    /* Move to sibling if present,skipping sub-tree */
   1873             reader->node = reader->node->next;
   1874             reader->state = XML_TEXTREADER_START;
   1875             return(1);
   1876         }
   1877 
   1878 	/* if reader->node->next is NULL mean no subtree for current node,
   1879 	so need to move to sibling of parent node if present */
   1880         if ((reader->node->type == XML_ELEMENT_NODE) ||
   1881             (reader->node->type == XML_ATTRIBUTE_NODE)) {
   1882             reader->state = XML_TEXTREADER_BACKTRACK;
   1883 	    /* This will move to parent if present */
   1884             xmlTextReaderRead(reader);
   1885         }
   1886     }
   1887 
   1888     if (reader->node->next != 0) {
   1889         reader->node = reader->node->next;
   1890         reader->state = XML_TEXTREADER_START;
   1891         return(1);
   1892     }
   1893 
   1894     if (reader->node->parent != 0) {
   1895         if (reader->node->parent->type == XML_DOCUMENT_NODE) {
   1896             reader->state = XML_TEXTREADER_END;
   1897             return(0);
   1898         }
   1899 
   1900         reader->node = reader->node->parent;
   1901         reader->depth--;
   1902         reader->state = XML_TEXTREADER_BACKTRACK;
   1903 	/* Repeat process to move to sibling of parent node if present */
   1904         xmlTextReaderNextTree(reader);
   1905     }
   1906 
   1907     reader->state = XML_TEXTREADER_END;
   1908 
   1909     return(1);
   1910 }
   1911 
   1912 /**
   1913  * xmlTextReaderReadTree:
   1914  * @reader:  the xmlTextReaderPtr used
   1915  *
   1916  *  Moves the position of the current instance to the next node in
   1917  *  the stream, exposing its properties.
   1918  *
   1919  *  Returns 1 if the node was read successfully, 0 if there is no more
   1920  *          nodes to read, or -1 in case of error
   1921  */
   1922 static int
   1923 xmlTextReaderReadTree(xmlTextReaderPtr reader) {
   1924     if (reader->state == XML_TEXTREADER_END)
   1925         return(0);
   1926 
   1927 next_node:
   1928     if (reader->node == NULL) {
   1929         if (reader->doc->children == NULL) {
   1930             reader->state = XML_TEXTREADER_END;
   1931             return(0);
   1932         }
   1933 
   1934         reader->node = reader->doc->children;
   1935         reader->state = XML_TEXTREADER_START;
   1936         goto found_node;
   1937     }
   1938 
   1939     if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
   1940         (reader->node->type != XML_DTD_NODE) &&
   1941         (reader->node->type != XML_XINCLUDE_START) &&
   1942 	(reader->node->type != XML_ENTITY_REF_NODE)) {
   1943         if (reader->node->children != NULL) {
   1944             reader->node = reader->node->children;
   1945             reader->depth++;
   1946             reader->state = XML_TEXTREADER_START;
   1947             goto found_node;
   1948         }
   1949 
   1950         if (reader->node->type == XML_ATTRIBUTE_NODE) {
   1951             reader->state = XML_TEXTREADER_BACKTRACK;
   1952             goto found_node;
   1953         }
   1954     }
   1955 
   1956     if (reader->node->next != NULL) {
   1957         reader->node = reader->node->next;
   1958         reader->state = XML_TEXTREADER_START;
   1959         goto found_node;
   1960     }
   1961 
   1962     if (reader->node->parent != NULL) {
   1963         if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
   1964 	    (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
   1965             reader->state = XML_TEXTREADER_END;
   1966             return(0);
   1967         }
   1968 
   1969         reader->node = reader->node->parent;
   1970         reader->depth--;
   1971         reader->state = XML_TEXTREADER_BACKTRACK;
   1972         goto found_node;
   1973     }
   1974 
   1975     reader->state = XML_TEXTREADER_END;
   1976 
   1977 found_node:
   1978     if ((reader->node->type == XML_XINCLUDE_START) ||
   1979         (reader->node->type == XML_XINCLUDE_END))
   1980 	goto next_node;
   1981 
   1982     return(1);
   1983 }
   1984 
   1985 /**
   1986  * xmlTextReaderNextSibling:
   1987  * @reader:  the xmlTextReaderPtr used
   1988  *
   1989  * Skip to the node following the current one in document order while
   1990  * avoiding the subtree if any.
   1991  * Currently implemented only for Readers built on a document
   1992  *
   1993  * Returns 1 if the node was read successfully, 0 if there is no more
   1994  *          nodes to read, or -1 in case of error
   1995  */
   1996 int
   1997 xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
   1998     if (reader == NULL)
   1999         return(-1);
   2000     if (reader->doc == NULL) {
   2001         /* TODO */
   2002 	return(-1);
   2003     }
   2004 
   2005     if (reader->state == XML_TEXTREADER_END)
   2006         return(0);
   2007 
   2008     if (reader->node == NULL)
   2009         return(xmlTextReaderNextTree(reader));
   2010 
   2011     if (reader->node->next != NULL) {
   2012         reader->node = reader->node->next;
   2013         reader->state = XML_TEXTREADER_START;
   2014         return(1);
   2015     }
   2016 
   2017     return(0);
   2018 }
   2019 
   2020 /************************************************************************
   2021  *									*
   2022  *			Constructor and destructors			*
   2023  *									*
   2024  ************************************************************************/
   2025 /**
   2026  * xmlNewTextReader:
   2027  * @input: the xmlParserInputBufferPtr used to read data
   2028  * @URI: the URI information for the source if available
   2029  *
   2030  * Create an xmlTextReader structure fed with @input
   2031  *
   2032  * Returns the new xmlTextReaderPtr or NULL in case of error
   2033  */
   2034 xmlTextReaderPtr
   2035 xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
   2036     xmlTextReaderPtr ret;
   2037 
   2038     if (input == NULL)
   2039 	return(NULL);
   2040     ret = xmlMalloc(sizeof(xmlTextReader));
   2041     if (ret == NULL) {
   2042         xmlGenericError(xmlGenericErrorContext,
   2043 		"xmlNewTextReader : malloc failed\n");
   2044 	return(NULL);
   2045     }
   2046     memset(ret, 0, sizeof(xmlTextReader));
   2047     ret->doc = NULL;
   2048     ret->entTab = NULL;
   2049     ret->entMax = 0;
   2050     ret->entNr = 0;
   2051     ret->input = input;
   2052     ret->buffer = xmlBufferCreateSize(100);
   2053     if (ret->buffer == NULL) {
   2054         xmlFree(ret);
   2055         xmlGenericError(xmlGenericErrorContext,
   2056 		"xmlNewTextReader : malloc failed\n");
   2057 	return(NULL);
   2058     }
   2059     ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
   2060     if (ret->sax == NULL) {
   2061 	xmlBufferFree(ret->buffer);
   2062 	xmlFree(ret);
   2063         xmlGenericError(xmlGenericErrorContext,
   2064 		"xmlNewTextReader : malloc failed\n");
   2065 	return(NULL);
   2066     }
   2067     xmlSAXVersion(ret->sax, 2);
   2068     ret->startElement = ret->sax->startElement;
   2069     ret->sax->startElement = xmlTextReaderStartElement;
   2070     ret->endElement = ret->sax->endElement;
   2071     ret->sax->endElement = xmlTextReaderEndElement;
   2072 #ifdef LIBXML_SAX1_ENABLED
   2073     if (ret->sax->initialized == XML_SAX2_MAGIC) {
   2074 #endif /* LIBXML_SAX1_ENABLED */
   2075 	ret->startElementNs = ret->sax->startElementNs;
   2076 	ret->sax->startElementNs = xmlTextReaderStartElementNs;
   2077 	ret->endElementNs = ret->sax->endElementNs;
   2078 	ret->sax->endElementNs = xmlTextReaderEndElementNs;
   2079 #ifdef LIBXML_SAX1_ENABLED
   2080     } else {
   2081 	ret->startElementNs = NULL;
   2082 	ret->endElementNs = NULL;
   2083     }
   2084 #endif /* LIBXML_SAX1_ENABLED */
   2085     ret->characters = ret->sax->characters;
   2086     ret->sax->characters = xmlTextReaderCharacters;
   2087     ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
   2088     ret->cdataBlock = ret->sax->cdataBlock;
   2089     ret->sax->cdataBlock = xmlTextReaderCDataBlock;
   2090 
   2091     ret->mode = XML_TEXTREADER_MODE_INITIAL;
   2092     ret->node = NULL;
   2093     ret->curnode = NULL;
   2094     if (ret->input->buffer->use < 4) {
   2095 	xmlParserInputBufferRead(input, 4);
   2096     }
   2097     if (ret->input->buffer->use >= 4) {
   2098 	ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
   2099 			(const char *) ret->input->buffer->content, 4, URI);
   2100 	ret->base = 0;
   2101 	ret->cur = 4;
   2102     } else {
   2103 	ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
   2104 	ret->base = 0;
   2105 	ret->cur = 0;
   2106     }
   2107 
   2108     if (ret->ctxt == NULL) {
   2109         xmlGenericError(xmlGenericErrorContext,
   2110 		"xmlNewTextReader : malloc failed\n");
   2111 	xmlBufferFree(ret->buffer);
   2112 	xmlFree(ret->sax);
   2113 	xmlFree(ret);
   2114 	return(NULL);
   2115     }
   2116     ret->ctxt->parseMode = XML_PARSE_READER;
   2117     ret->ctxt->_private = ret;
   2118     ret->ctxt->linenumbers = 1;
   2119     ret->ctxt->dictNames = 1;
   2120     ret->allocs = XML_TEXTREADER_CTXT;
   2121     /*
   2122      * use the parser dictionnary to allocate all elements and attributes names
   2123      */
   2124     ret->ctxt->docdict = 1;
   2125     ret->dict = ret->ctxt->dict;
   2126 #ifdef LIBXML_XINCLUDE_ENABLED
   2127     ret->xinclude = 0;
   2128 #endif
   2129 #ifdef LIBXML_PATTERN_ENABLED
   2130     ret->patternMax = 0;
   2131     ret->patternTab = NULL;
   2132 #endif
   2133     return(ret);
   2134 }
   2135 
   2136 /**
   2137  * xmlNewTextReaderFilename:
   2138  * @URI: the URI of the resource to process
   2139  *
   2140  * Create an xmlTextReader structure fed with the resource at @URI
   2141  *
   2142  * Returns the new xmlTextReaderPtr or NULL in case of error
   2143  */
   2144 xmlTextReaderPtr
   2145 xmlNewTextReaderFilename(const char *URI) {
   2146     xmlParserInputBufferPtr input;
   2147     xmlTextReaderPtr ret;
   2148     char *directory = NULL;
   2149 
   2150     input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
   2151     if (input == NULL)
   2152 	return(NULL);
   2153     ret = xmlNewTextReader(input, URI);
   2154     if (ret == NULL) {
   2155 	xmlFreeParserInputBuffer(input);
   2156 	return(NULL);
   2157     }
   2158     ret->allocs |= XML_TEXTREADER_INPUT;
   2159     if (ret->ctxt->directory == NULL)
   2160         directory = xmlParserGetDirectory(URI);
   2161     if ((ret->ctxt->directory == NULL) && (directory != NULL))
   2162         ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
   2163     if (directory != NULL)
   2164 	xmlFree(directory);
   2165     return(ret);
   2166 }
   2167 
   2168 /**
   2169  * xmlFreeTextReader:
   2170  * @reader:  the xmlTextReaderPtr
   2171  *
   2172  * Deallocate all the resources associated to the reader
   2173  */
   2174 void
   2175 xmlFreeTextReader(xmlTextReaderPtr reader) {
   2176     if (reader == NULL)
   2177 	return;
   2178 #ifdef LIBXML_SCHEMAS_ENABLED
   2179     if (reader->rngSchemas != NULL) {
   2180 	xmlRelaxNGFree(reader->rngSchemas);
   2181 	reader->rngSchemas = NULL;
   2182     }
   2183     if (reader->rngValidCtxt != NULL) {
   2184 	xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
   2185 	reader->rngValidCtxt = NULL;
   2186     }
   2187     if (reader->xsdPlug != NULL) {
   2188 	xmlSchemaSAXUnplug(reader->xsdPlug);
   2189 	reader->xsdPlug = NULL;
   2190     }
   2191     if (reader->xsdValidCtxt != NULL) {
   2192 	if (! reader->xsdPreserveCtxt)
   2193 	    xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
   2194 	reader->xsdValidCtxt = NULL;
   2195     }
   2196     if (reader->xsdSchemas != NULL) {
   2197 	xmlSchemaFree(reader->xsdSchemas);
   2198 	reader->xsdSchemas = NULL;
   2199     }
   2200 #endif
   2201 #ifdef LIBXML_XINCLUDE_ENABLED
   2202     if (reader->xincctxt != NULL)
   2203 	xmlXIncludeFreeContext(reader->xincctxt);
   2204 #endif
   2205 #ifdef LIBXML_PATTERN_ENABLED
   2206     if (reader->patternTab != NULL) {
   2207         int i;
   2208 	for (i = 0;i < reader->patternNr;i++) {
   2209 	    if (reader->patternTab[i] != NULL)
   2210 	        xmlFreePattern(reader->patternTab[i]);
   2211 	}
   2212 	xmlFree(reader->patternTab);
   2213     }
   2214 #endif
   2215     if (reader->faketext != NULL) {
   2216 	xmlFreeNode(reader->faketext);
   2217     }
   2218     if (reader->ctxt != NULL) {
   2219         if (reader->dict == reader->ctxt->dict)
   2220 	    reader->dict = NULL;
   2221 	if (reader->ctxt->myDoc != NULL) {
   2222 	    if (reader->preserve == 0)
   2223 		xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
   2224 	    reader->ctxt->myDoc = NULL;
   2225 	}
   2226 	if ((reader->ctxt->vctxt.vstateTab != NULL) &&
   2227 	    (reader->ctxt->vctxt.vstateMax > 0)){
   2228 	    xmlFree(reader->ctxt->vctxt.vstateTab);
   2229 	    reader->ctxt->vctxt.vstateTab = NULL;
   2230 	    reader->ctxt->vctxt.vstateMax = 0;
   2231 	}
   2232 	if (reader->allocs & XML_TEXTREADER_CTXT)
   2233 	    xmlFreeParserCtxt(reader->ctxt);
   2234     }
   2235     if (reader->sax != NULL)
   2236 	xmlFree(reader->sax);
   2237     if ((reader->input != NULL)  && (reader->allocs & XML_TEXTREADER_INPUT))
   2238 	xmlFreeParserInputBuffer(reader->input);
   2239     if (reader->buffer != NULL)
   2240         xmlBufferFree(reader->buffer);
   2241     if (reader->entTab != NULL)
   2242 	xmlFree(reader->entTab);
   2243     if (reader->dict != NULL)
   2244         xmlDictFree(reader->dict);
   2245     xmlFree(reader);
   2246 }
   2247 
   2248 /************************************************************************
   2249  *									*
   2250  *			Methods for XmlTextReader			*
   2251  *									*
   2252  ************************************************************************/
   2253 /**
   2254  * xmlTextReaderClose:
   2255  * @reader:  the xmlTextReaderPtr used
   2256  *
   2257  * This method releases any resources allocated by the current instance
   2258  * changes the state to Closed and close any underlying input.
   2259  *
   2260  * Returns 0 or -1 in case of error
   2261  */
   2262 int
   2263 xmlTextReaderClose(xmlTextReaderPtr reader) {
   2264     if (reader == NULL)
   2265 	return(-1);
   2266     reader->node = NULL;
   2267     reader->curnode = NULL;
   2268     reader->mode = XML_TEXTREADER_MODE_CLOSED;
   2269     if (reader->ctxt != NULL) {
   2270 	xmlStopParser(reader->ctxt);
   2271 	if (reader->ctxt->myDoc != NULL) {
   2272 	    if (reader->preserve == 0)
   2273 		xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
   2274 	    reader->ctxt->myDoc = NULL;
   2275 	}
   2276     }
   2277     if ((reader->input != NULL)  && (reader->allocs & XML_TEXTREADER_INPUT)) {
   2278 	xmlFreeParserInputBuffer(reader->input);
   2279 	reader->allocs -= XML_TEXTREADER_INPUT;
   2280     }
   2281     return(0);
   2282 }
   2283 
   2284 /**
   2285  * xmlTextReaderGetAttributeNo:
   2286  * @reader:  the xmlTextReaderPtr used
   2287  * @no: the zero-based index of the attribute relative to the containing element
   2288  *
   2289  * Provides the value of the attribute with the specified index relative
   2290  * to the containing element.
   2291  *
   2292  * Returns a string containing the value of the specified attribute, or NULL
   2293  *    in case of error. The string must be deallocated by the caller.
   2294  */
   2295 xmlChar *
   2296 xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
   2297     xmlChar *ret;
   2298     int i;
   2299     xmlAttrPtr cur;
   2300     xmlNsPtr ns;
   2301 
   2302     if (reader == NULL)
   2303 	return(NULL);
   2304     if (reader->node == NULL)
   2305 	return(NULL);
   2306     if (reader->curnode != NULL)
   2307 	return(NULL);
   2308     /* TODO: handle the xmlDecl */
   2309     if (reader->node->type != XML_ELEMENT_NODE)
   2310 	return(NULL);
   2311 
   2312     ns = reader->node->nsDef;
   2313     for (i = 0;(i < no) && (ns != NULL);i++) {
   2314 	ns = ns->next;
   2315     }
   2316     if (ns != NULL)
   2317 	return(xmlStrdup(ns->href));
   2318 
   2319     cur = reader->node->properties;
   2320     if (cur == NULL)
   2321 	return(NULL);
   2322     for (;i < no;i++) {
   2323 	cur = cur->next;
   2324 	if (cur == NULL)
   2325 	    return(NULL);
   2326     }
   2327     /* TODO walk the DTD if present */
   2328 
   2329     ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
   2330     if (ret == NULL) return(xmlStrdup((xmlChar *)""));
   2331     return(ret);
   2332 }
   2333 
   2334 /**
   2335  * xmlTextReaderGetAttribute:
   2336  * @reader:  the xmlTextReaderPtr used
   2337  * @name: the qualified name of the attribute.
   2338  *
   2339  * Provides the value of the attribute with the specified qualified name.
   2340  *
   2341  * Returns a string containing the value of the specified attribute, or NULL
   2342  *    in case of error. The string must be deallocated by the caller.
   2343  */
   2344 xmlChar *
   2345 xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
   2346     xmlChar *prefix = NULL;
   2347     xmlChar *localname;
   2348     xmlNsPtr ns;
   2349     xmlChar *ret = NULL;
   2350 
   2351     if ((reader == NULL) || (name == NULL))
   2352 	return(NULL);
   2353     if (reader->node == NULL)
   2354 	return(NULL);
   2355     if (reader->curnode != NULL)
   2356 	return(NULL);
   2357 
   2358     /* TODO: handle the xmlDecl */
   2359     if (reader->node->type != XML_ELEMENT_NODE)
   2360 	return(NULL);
   2361 
   2362     localname = xmlSplitQName2(name, &prefix);
   2363     if (localname == NULL) {
   2364 		/*
   2365 		 * Namespace default decl
   2366 		 */
   2367 		if (xmlStrEqual(name, BAD_CAST "xmlns")) {
   2368 			ns = reader->node->nsDef;
   2369 			while (ns != NULL) {
   2370 				if (ns->prefix == NULL) {
   2371 					return(xmlStrdup(ns->href));
   2372 				}
   2373 				ns = ns->next;
   2374 			}
   2375 			return NULL;
   2376 		}
   2377 		return(xmlGetNoNsProp(reader->node, name));
   2378 	}
   2379 
   2380     /*
   2381      * Namespace default decl
   2382      */
   2383     if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
   2384 		ns = reader->node->nsDef;
   2385 		while (ns != NULL) {
   2386 			if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
   2387 				ret = xmlStrdup(ns->href);
   2388 				break;
   2389 			}
   2390 			ns = ns->next;
   2391 		}
   2392     } else {
   2393 		ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
   2394 		if (ns != NULL)
   2395 			ret = xmlGetNsProp(reader->node, localname, ns->href);
   2396 	}
   2397 
   2398     xmlFree(localname);
   2399     if (prefix != NULL)
   2400         xmlFree(prefix);
   2401     return(ret);
   2402 }
   2403 
   2404 
   2405 /**
   2406  * xmlTextReaderGetAttributeNs:
   2407  * @reader:  the xmlTextReaderPtr used
   2408  * @localName: the local name of the attribute.
   2409  * @namespaceURI: the namespace URI of the attribute.
   2410  *
   2411  * Provides the value of the specified attribute
   2412  *
   2413  * Returns a string containing the value of the specified attribute, or NULL
   2414  *    in case of error. The string must be deallocated by the caller.
   2415  */
   2416 xmlChar *
   2417 xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
   2418 			    const xmlChar *namespaceURI) {
   2419     xmlChar *prefix = NULL;
   2420     xmlNsPtr ns;
   2421 
   2422     if ((reader == NULL) || (localName == NULL))
   2423 	return(NULL);
   2424     if (reader->node == NULL)
   2425 	return(NULL);
   2426     if (reader->curnode != NULL)
   2427 	return(NULL);
   2428 
   2429     /* TODO: handle the xmlDecl */
   2430     if (reader->node->type != XML_ELEMENT_NODE)
   2431 	return(NULL);
   2432 
   2433     if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
   2434 		if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
   2435 			prefix = BAD_CAST localName;
   2436 		}
   2437 		ns = reader->node->nsDef;
   2438 		while (ns != NULL) {
   2439 			if ((prefix == NULL && ns->prefix == NULL) ||
   2440 				((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
   2441 				return xmlStrdup(ns->href);
   2442 			}
   2443 			ns = ns->next;
   2444 		}
   2445 		return NULL;
   2446     }
   2447 
   2448     return(xmlGetNsProp(reader->node, localName, namespaceURI));
   2449 }
   2450 
   2451 /**
   2452  * xmlTextReaderGetRemainder:
   2453  * @reader:  the xmlTextReaderPtr used
   2454  *
   2455  * Method to get the remainder of the buffered XML. this method stops the
   2456  * parser, set its state to End Of File and return the input stream with
   2457  * what is left that the parser did not use.
   2458  *
   2459  * The implementation is not good, the parser certainly procgressed past
   2460  * what's left in reader->input, and there is an allocation problem. Best
   2461  * would be to rewrite it differently.
   2462  *
   2463  * Returns the xmlParserInputBufferPtr attached to the XML or NULL
   2464  *    in case of error.
   2465  */
   2466 xmlParserInputBufferPtr
   2467 xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
   2468     xmlParserInputBufferPtr ret = NULL;
   2469 
   2470     if (reader == NULL)
   2471 	return(NULL);
   2472     if (reader->node == NULL)
   2473 	return(NULL);
   2474 
   2475     reader->node = NULL;
   2476     reader->curnode = NULL;
   2477     reader->mode = XML_TEXTREADER_MODE_EOF;
   2478     if (reader->ctxt != NULL) {
   2479 	xmlStopParser(reader->ctxt);
   2480 	if (reader->ctxt->myDoc != NULL) {
   2481 	    if (reader->preserve == 0)
   2482 		xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
   2483 	    reader->ctxt->myDoc = NULL;
   2484 	}
   2485     }
   2486     if (reader->allocs & XML_TEXTREADER_INPUT) {
   2487 	ret = reader->input;
   2488 	reader->input = NULL;
   2489 	reader->allocs -= XML_TEXTREADER_INPUT;
   2490     } else {
   2491 	/*
   2492 	 * Hum, one may need to duplicate the data structure because
   2493 	 * without reference counting the input may be freed twice:
   2494 	 *   - by the layer which allocated it.
   2495 	 *   - by the layer to which would have been returned to.
   2496 	 */
   2497 	TODO
   2498 	return(NULL);
   2499     }
   2500     return(ret);
   2501 }
   2502 
   2503 /**
   2504  * xmlTextReaderLookupNamespace:
   2505  * @reader:  the xmlTextReaderPtr used
   2506  * @prefix: the prefix whose namespace URI is to be resolved. To return
   2507  *          the default namespace, specify NULL
   2508  *
   2509  * Resolves a namespace prefix in the scope of the current element.
   2510  *
   2511  * Returns a string containing the namespace URI to which the prefix maps
   2512  *    or NULL in case of error. The string must be deallocated by the caller.
   2513  */
   2514 xmlChar *
   2515 xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
   2516     xmlNsPtr ns;
   2517 
   2518     if (reader == NULL)
   2519 	return(NULL);
   2520     if (reader->node == NULL)
   2521 	return(NULL);
   2522 
   2523     ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
   2524     if (ns == NULL)
   2525 	return(NULL);
   2526     return(xmlStrdup(ns->href));
   2527 }
   2528 
   2529 /**
   2530  * xmlTextReaderMoveToAttributeNo:
   2531  * @reader:  the xmlTextReaderPtr used
   2532  * @no: the zero-based index of the attribute relative to the containing
   2533  *      element.
   2534  *
   2535  * Moves the position of the current instance to the attribute with
   2536  * the specified index relative to the containing element.
   2537  *
   2538  * Returns 1 in case of success, -1 in case of error, 0 if not found
   2539  */
   2540 int
   2541 xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
   2542     int i;
   2543     xmlAttrPtr cur;
   2544     xmlNsPtr ns;
   2545 
   2546     if (reader == NULL)
   2547 	return(-1);
   2548     if (reader->node == NULL)
   2549 	return(-1);
   2550     /* TODO: handle the xmlDecl */
   2551     if (reader->node->type != XML_ELEMENT_NODE)
   2552 	return(-1);
   2553 
   2554     reader->curnode = NULL;
   2555 
   2556     ns = reader->node->nsDef;
   2557     for (i = 0;(i < no) && (ns != NULL);i++) {
   2558 	ns = ns->next;
   2559     }
   2560     if (ns != NULL) {
   2561 	reader->curnode = (xmlNodePtr) ns;
   2562 	return(1);
   2563     }
   2564 
   2565     cur = reader->node->properties;
   2566     if (cur == NULL)
   2567 	return(0);
   2568     for (;i < no;i++) {
   2569 	cur = cur->next;
   2570 	if (cur == NULL)
   2571 	    return(0);
   2572     }
   2573     /* TODO walk the DTD if present */
   2574 
   2575     reader->curnode = (xmlNodePtr) cur;
   2576     return(1);
   2577 }
   2578 
   2579 /**
   2580  * xmlTextReaderMoveToAttribute:
   2581  * @reader:  the xmlTextReaderPtr used
   2582  * @name: the qualified name of the attribute.
   2583  *
   2584  * Moves the position of the current instance to the attribute with
   2585  * the specified qualified name.
   2586  *
   2587  * Returns 1 in case of success, -1 in case of error, 0 if not found
   2588  */
   2589 int
   2590 xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
   2591     xmlChar *prefix = NULL;
   2592     xmlChar *localname;
   2593     xmlNsPtr ns;
   2594     xmlAttrPtr prop;
   2595 
   2596     if ((reader == NULL) || (name == NULL))
   2597 	return(-1);
   2598     if (reader->node == NULL)
   2599 	return(-1);
   2600 
   2601     /* TODO: handle the xmlDecl */
   2602     if (reader->node->type != XML_ELEMENT_NODE)
   2603 	return(0);
   2604 
   2605     localname = xmlSplitQName2(name, &prefix);
   2606     if (localname == NULL) {
   2607 	/*
   2608 	 * Namespace default decl
   2609 	 */
   2610 	if (xmlStrEqual(name, BAD_CAST "xmlns")) {
   2611 	    ns = reader->node->nsDef;
   2612 	    while (ns != NULL) {
   2613 		if (ns->prefix == NULL) {
   2614 		    reader->curnode = (xmlNodePtr) ns;
   2615 		    return(1);
   2616 		}
   2617 		ns = ns->next;
   2618 	    }
   2619 	    return(0);
   2620 	}
   2621 
   2622 	prop = reader->node->properties;
   2623 	while (prop != NULL) {
   2624 	    /*
   2625 	     * One need to have
   2626 	     *   - same attribute names
   2627 	     *   - and the attribute carrying that namespace
   2628 	     */
   2629 	    if ((xmlStrEqual(prop->name, name)) &&
   2630 		((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
   2631 		reader->curnode = (xmlNodePtr) prop;
   2632 		return(1);
   2633 	    }
   2634 	    prop = prop->next;
   2635 	}
   2636 	return(0);
   2637     }
   2638 
   2639     /*
   2640      * Namespace default decl
   2641      */
   2642     if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
   2643 	ns = reader->node->nsDef;
   2644 	while (ns != NULL) {
   2645 	    if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
   2646 		reader->curnode = (xmlNodePtr) ns;
   2647 		goto found;
   2648 	    }
   2649 	    ns = ns->next;
   2650 	}
   2651 	goto not_found;
   2652     }
   2653     prop = reader->node->properties;
   2654     while (prop != NULL) {
   2655 	/*
   2656 	 * One need to have
   2657 	 *   - same attribute names
   2658 	 *   - and the attribute carrying that namespace
   2659 	 */
   2660 	if ((xmlStrEqual(prop->name, localname)) &&
   2661 	    (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
   2662 	    reader->curnode = (xmlNodePtr) prop;
   2663 	    goto found;
   2664 	}
   2665 	prop = prop->next;
   2666     }
   2667 not_found:
   2668     if (localname != NULL)
   2669         xmlFree(localname);
   2670     if (prefix != NULL)
   2671         xmlFree(prefix);
   2672     return(0);
   2673 
   2674 found:
   2675     if (localname != NULL)
   2676         xmlFree(localname);
   2677     if (prefix != NULL)
   2678         xmlFree(prefix);
   2679     return(1);
   2680 }
   2681 
   2682 /**
   2683  * xmlTextReaderMoveToAttributeNs:
   2684  * @reader:  the xmlTextReaderPtr used
   2685  * @localName:  the local name of the attribute.
   2686  * @namespaceURI:  the namespace URI of the attribute.
   2687  *
   2688  * Moves the position of the current instance to the attribute with the
   2689  * specified local name and namespace URI.
   2690  *
   2691  * Returns 1 in case of success, -1 in case of error, 0 if not found
   2692  */
   2693 int
   2694 xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
   2695 	const xmlChar *localName, const xmlChar *namespaceURI) {
   2696     xmlAttrPtr prop;
   2697     xmlNodePtr node;
   2698     xmlNsPtr ns;
   2699     xmlChar *prefix = NULL;
   2700 
   2701     if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
   2702 	return(-1);
   2703     if (reader->node == NULL)
   2704 	return(-1);
   2705     if (reader->node->type != XML_ELEMENT_NODE)
   2706 	return(0);
   2707     node = reader->node;
   2708 
   2709     if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
   2710 		if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
   2711 			prefix = BAD_CAST localName;
   2712 		}
   2713 		ns = reader->node->nsDef;
   2714 		while (ns != NULL) {
   2715 			if ((prefix == NULL && ns->prefix == NULL) ||
   2716 				((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
   2717 				reader->curnode = (xmlNodePtr) ns;
   2718 				return(1);
   2719 			}
   2720 			ns = ns->next;
   2721 		}
   2722 		return(0);
   2723     }
   2724 
   2725     prop = node->properties;
   2726     while (prop != NULL) {
   2727 	/*
   2728 	 * One need to have
   2729 	 *   - same attribute names
   2730 	 *   - and the attribute carrying that namespace
   2731 	 */
   2732         if (xmlStrEqual(prop->name, localName) &&
   2733 	    ((prop->ns != NULL) &&
   2734 	     (xmlStrEqual(prop->ns->href, namespaceURI)))) {
   2735 	    reader->curnode = (xmlNodePtr) prop;
   2736 	    return(1);
   2737         }
   2738 	prop = prop->next;
   2739     }
   2740     return(0);
   2741 }
   2742 
   2743 /**
   2744  * xmlTextReaderMoveToFirstAttribute:
   2745  * @reader:  the xmlTextReaderPtr used
   2746  *
   2747  * Moves the position of the current instance to the first attribute
   2748  * associated with the current node.
   2749  *
   2750  * Returns 1 in case of success, -1 in case of error, 0 if not found
   2751  */
   2752 int
   2753 xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
   2754     if (reader == NULL)
   2755 	return(-1);
   2756     if (reader->node == NULL)
   2757 	return(-1);
   2758     if (reader->node->type != XML_ELEMENT_NODE)
   2759 	return(0);
   2760 
   2761     if (reader->node->nsDef != NULL) {
   2762 	reader->curnode = (xmlNodePtr) reader->node->nsDef;
   2763 	return(1);
   2764     }
   2765     if (reader->node->properties != NULL) {
   2766 	reader->curnode = (xmlNodePtr) reader->node->properties;
   2767 	return(1);
   2768     }
   2769     return(0);
   2770 }
   2771 
   2772 /**
   2773  * xmlTextReaderMoveToNextAttribute:
   2774  * @reader:  the xmlTextReaderPtr used
   2775  *
   2776  * Moves the position of the current instance to the next attribute
   2777  * associated with the current node.
   2778  *
   2779  * Returns 1 in case of success, -1 in case of error, 0 if not found
   2780  */
   2781 int
   2782 xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
   2783     if (reader == NULL)
   2784 	return(-1);
   2785     if (reader->node == NULL)
   2786 	return(-1);
   2787     if (reader->node->type != XML_ELEMENT_NODE)
   2788 	return(0);
   2789     if (reader->curnode == NULL)
   2790 	return(xmlTextReaderMoveToFirstAttribute(reader));
   2791 
   2792     if (reader->curnode->type == XML_NAMESPACE_DECL) {
   2793 	xmlNsPtr ns = (xmlNsPtr) reader->curnode;
   2794 	if (ns->next != NULL) {
   2795 	    reader->curnode = (xmlNodePtr) ns->next;
   2796 	    return(1);
   2797 	}
   2798 	if (reader->node->properties != NULL) {
   2799 	    reader->curnode = (xmlNodePtr) reader->node->properties;
   2800 	    return(1);
   2801 	}
   2802 	return(0);
   2803     } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
   2804 	       (reader->curnode->next != NULL)) {
   2805 	reader->curnode = reader->curnode->next;
   2806 	return(1);
   2807     }
   2808     return(0);
   2809 }
   2810 
   2811 /**
   2812  * xmlTextReaderMoveToElement:
   2813  * @reader:  the xmlTextReaderPtr used
   2814  *
   2815  * Moves the position of the current instance to the node that
   2816  * contains the current Attribute  node.
   2817  *
   2818  * Returns 1 in case of success, -1 in case of error, 0 if not moved
   2819  */
   2820 int
   2821 xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
   2822     if (reader == NULL)
   2823 	return(-1);
   2824     if (reader->node == NULL)
   2825 	return(-1);
   2826     if (reader->node->type != XML_ELEMENT_NODE)
   2827 	return(0);
   2828     if (reader->curnode != NULL) {
   2829 	reader->curnode = NULL;
   2830 	return(1);
   2831     }
   2832     return(0);
   2833 }
   2834 
   2835 /**
   2836  * xmlTextReaderReadAttributeValue:
   2837  * @reader:  the xmlTextReaderPtr used
   2838  *
   2839  * Parses an attribute value into one or more Text and EntityReference nodes.
   2840  *
   2841  * Returns 1 in case of success, 0 if the reader was not positionned on an
   2842  *         ttribute node or all the attribute values have been read, or -1
   2843  *         in case of error.
   2844  */
   2845 int
   2846 xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
   2847     if (reader == NULL)
   2848 	return(-1);
   2849     if (reader->node == NULL)
   2850 	return(-1);
   2851     if (reader->curnode == NULL)
   2852 	return(0);
   2853     if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
   2854 	if (reader->curnode->children == NULL)
   2855 	    return(0);
   2856 	reader->curnode = reader->curnode->children;
   2857     } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
   2858 	xmlNsPtr ns = (xmlNsPtr) reader->curnode;
   2859 
   2860 	if (reader->faketext == NULL) {
   2861 	    reader->faketext = xmlNewDocText(reader->node->doc,
   2862 		                             ns->href);
   2863 	} else {
   2864             if ((reader->faketext->content != NULL) &&
   2865 	        (reader->faketext->content !=
   2866 		 (xmlChar *) &(reader->faketext->properties)))
   2867 		xmlFree(reader->faketext->content);
   2868 	    reader->faketext->content = xmlStrdup(ns->href);
   2869 	}
   2870 	reader->curnode = reader->faketext;
   2871     } else {
   2872 	if (reader->curnode->next == NULL)
   2873 	    return(0);
   2874 	reader->curnode = reader->curnode->next;
   2875     }
   2876     return(1);
   2877 }
   2878 
   2879 /**
   2880  * xmlTextReaderConstEncoding:
   2881  * @reader:  the xmlTextReaderPtr used
   2882  *
   2883  * Determine the encoding of the document being read.
   2884  *
   2885  * Returns a string containing the encoding of the document or NULL in
   2886  * case of error.  The string is deallocated with the reader.
   2887  */
   2888 const xmlChar *
   2889 xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
   2890     xmlDocPtr doc = NULL;
   2891     if (reader == NULL)
   2892 	return(NULL);
   2893     if (reader->doc != NULL)
   2894         doc = reader->doc;
   2895     else if (reader->ctxt != NULL)
   2896 	doc = reader->ctxt->myDoc;
   2897     if (doc == NULL)
   2898 	return(NULL);
   2899 
   2900     if (doc->encoding == NULL)
   2901 	return(NULL);
   2902     else
   2903       return(CONSTSTR(doc->encoding));
   2904 }
   2905 
   2906 
   2907 /************************************************************************
   2908  *									*
   2909  *			Acces API to the current node			*
   2910  *									*
   2911  ************************************************************************/
   2912 /**
   2913  * xmlTextReaderAttributeCount:
   2914  * @reader:  the xmlTextReaderPtr used
   2915  *
   2916  * Provides the number of attributes of the current node
   2917  *
   2918  * Returns 0 i no attributes, -1 in case of error or the attribute count
   2919  */
   2920 int
   2921 xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
   2922     int ret;
   2923     xmlAttrPtr attr;
   2924     xmlNsPtr ns;
   2925     xmlNodePtr node;
   2926 
   2927     if (reader == NULL)
   2928 	return(-1);
   2929     if (reader->node == NULL)
   2930 	return(0);
   2931 
   2932     if (reader->curnode != NULL)
   2933 	node = reader->curnode;
   2934     else
   2935 	node = reader->node;
   2936 
   2937     if (node->type != XML_ELEMENT_NODE)
   2938 	return(0);
   2939     if ((reader->state == XML_TEXTREADER_END) ||
   2940 	(reader->state == XML_TEXTREADER_BACKTRACK))
   2941 	return(0);
   2942     ret = 0;
   2943     attr = node->properties;
   2944     while (attr != NULL) {
   2945 	ret++;
   2946 	attr = attr->next;
   2947     }
   2948     ns = node->nsDef;
   2949     while (ns != NULL) {
   2950 	ret++;
   2951 	ns = ns->next;
   2952     }
   2953     return(ret);
   2954 }
   2955 
   2956 /**
   2957  * xmlTextReaderNodeType:
   2958  * @reader:  the xmlTextReaderPtr used
   2959  *
   2960  * Get the node type of the current node
   2961  * Reference:
   2962  * http://www.gnu.org/software/dotgnu/pnetlib-doc/System/Xml/XmlNodeType.html
   2963  *
   2964  * Returns the xmlNodeType of the current node or -1 in case of error
   2965  */
   2966 int
   2967 xmlTextReaderNodeType(xmlTextReaderPtr reader) {
   2968     xmlNodePtr node;
   2969 
   2970     if (reader == NULL)
   2971 	return(-1);
   2972     if (reader->node == NULL)
   2973 	return(XML_READER_TYPE_NONE);
   2974     if (reader->curnode != NULL)
   2975 	node = reader->curnode;
   2976     else
   2977 	node = reader->node;
   2978     switch (node->type) {
   2979         case XML_ELEMENT_NODE:
   2980 	    if ((reader->state == XML_TEXTREADER_END) ||
   2981 		(reader->state == XML_TEXTREADER_BACKTRACK))
   2982 		return(XML_READER_TYPE_END_ELEMENT);
   2983 	    return(XML_READER_TYPE_ELEMENT);
   2984         case XML_NAMESPACE_DECL:
   2985         case XML_ATTRIBUTE_NODE:
   2986 	    return(XML_READER_TYPE_ATTRIBUTE);
   2987         case XML_TEXT_NODE:
   2988 	    if (xmlIsBlankNode(reader->node)) {
   2989 		if (xmlNodeGetSpacePreserve(reader->node))
   2990 		    return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
   2991 		else
   2992 		    return(XML_READER_TYPE_WHITESPACE);
   2993 	    } else {
   2994 		return(XML_READER_TYPE_TEXT);
   2995 	    }
   2996         case XML_CDATA_SECTION_NODE:
   2997 	    return(XML_READER_TYPE_CDATA);
   2998         case XML_ENTITY_REF_NODE:
   2999 	    return(XML_READER_TYPE_ENTITY_REFERENCE);
   3000         case XML_ENTITY_NODE:
   3001 	    return(XML_READER_TYPE_ENTITY);
   3002         case XML_PI_NODE:
   3003 	    return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
   3004         case XML_COMMENT_NODE:
   3005 	    return(XML_READER_TYPE_COMMENT);
   3006         case XML_DOCUMENT_NODE:
   3007         case XML_HTML_DOCUMENT_NODE:
   3008 #ifdef LIBXML_DOCB_ENABLED
   3009         case XML_DOCB_DOCUMENT_NODE:
   3010 #endif
   3011 	    return(XML_READER_TYPE_DOCUMENT);
   3012         case XML_DOCUMENT_FRAG_NODE:
   3013 	    return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
   3014         case XML_NOTATION_NODE:
   3015 	    return(XML_READER_TYPE_NOTATION);
   3016         case XML_DOCUMENT_TYPE_NODE:
   3017         case XML_DTD_NODE:
   3018 	    return(XML_READER_TYPE_DOCUMENT_TYPE);
   3019 
   3020         case XML_ELEMENT_DECL:
   3021         case XML_ATTRIBUTE_DECL:
   3022         case XML_ENTITY_DECL:
   3023         case XML_XINCLUDE_START:
   3024         case XML_XINCLUDE_END:
   3025 	    return(XML_READER_TYPE_NONE);
   3026     }
   3027     return(-1);
   3028 }
   3029 
   3030 /**
   3031  * xmlTextReaderIsEmptyElement:
   3032  * @reader:  the xmlTextReaderPtr used
   3033  *
   3034  * Check if the current node is empty
   3035  *
   3036  * Returns 1 if empty, 0 if not and -1 in case of error
   3037  */
   3038 int
   3039 xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
   3040     if ((reader == NULL) || (reader->node == NULL))
   3041 	return(-1);
   3042     if (reader->node->type != XML_ELEMENT_NODE)
   3043 	return(0);
   3044     if (reader->curnode != NULL)
   3045 	return(0);
   3046     if (reader->node->children != NULL)
   3047 	return(0);
   3048     if (reader->state == XML_TEXTREADER_END)
   3049 	return(0);
   3050     if (reader->doc != NULL)
   3051         return(1);
   3052 #ifdef LIBXML_XINCLUDE_ENABLED
   3053     if (reader->in_xinclude > 0)
   3054         return(1);
   3055 #endif
   3056     return((reader->node->extra & NODE_IS_EMPTY) != 0);
   3057 }
   3058 
   3059 /**
   3060  * xmlTextReaderLocalName:
   3061  * @reader:  the xmlTextReaderPtr used
   3062  *
   3063  * The local name of the node.
   3064  *
   3065  * Returns the local name or NULL if not available,
   3066  *   if non NULL it need to be freed by the caller.
   3067  */
   3068 xmlChar *
   3069 xmlTextReaderLocalName(xmlTextReaderPtr reader) {
   3070     xmlNodePtr node;
   3071     if ((reader == NULL) || (reader->node == NULL))
   3072 	return(NULL);
   3073     if (reader->curnode != NULL)
   3074 	node = reader->curnode;
   3075     else
   3076 	node = reader->node;
   3077     if (node->type == XML_NAMESPACE_DECL) {
   3078 	xmlNsPtr ns = (xmlNsPtr) node;
   3079 	if (ns->prefix == NULL)
   3080 	    return(xmlStrdup(BAD_CAST "xmlns"));
   3081 	else
   3082 	    return(xmlStrdup(ns->prefix));
   3083     }
   3084     if ((node->type != XML_ELEMENT_NODE) &&
   3085 	(node->type != XML_ATTRIBUTE_NODE))
   3086 	return(xmlTextReaderName(reader));
   3087     return(xmlStrdup(node->name));
   3088 }
   3089 
   3090 /**
   3091  * xmlTextReaderConstLocalName:
   3092  * @reader:  the xmlTextReaderPtr used
   3093  *
   3094  * The local name of the node.
   3095  *
   3096  * Returns the local name or NULL if not available, the
   3097  *         string will be deallocated with the reader.
   3098  */
   3099 const xmlChar *
   3100 xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
   3101     xmlNodePtr node;
   3102     if ((reader == NULL) || (reader->node == NULL))
   3103 	return(NULL);
   3104     if (reader->curnode != NULL)
   3105 	node = reader->curnode;
   3106     else
   3107 	node = reader->node;
   3108     if (node->type == XML_NAMESPACE_DECL) {
   3109 	xmlNsPtr ns = (xmlNsPtr) node;
   3110 	if (ns->prefix == NULL)
   3111 	    return(CONSTSTR(BAD_CAST "xmlns"));
   3112 	else
   3113 	    return(ns->prefix);
   3114     }
   3115     if ((node->type != XML_ELEMENT_NODE) &&
   3116 	(node->type != XML_ATTRIBUTE_NODE))
   3117 	return(xmlTextReaderConstName(reader));
   3118     return(node->name);
   3119 }
   3120 
   3121 /**
   3122  * xmlTextReaderName:
   3123  * @reader:  the xmlTextReaderPtr used
   3124  *
   3125  * The qualified name of the node, equal to Prefix :LocalName.
   3126  *
   3127  * Returns the local name or NULL if not available,
   3128  *   if non NULL it need to be freed by the caller.
   3129  */
   3130 xmlChar *
   3131 xmlTextReaderName(xmlTextReaderPtr reader) {
   3132     xmlNodePtr node;
   3133     xmlChar *ret;
   3134 
   3135     if ((reader == NULL) || (reader->node == NULL))
   3136 	return(NULL);
   3137     if (reader->curnode != NULL)
   3138 	node = reader->curnode;
   3139     else
   3140 	node = reader->node;
   3141     switch (node->type) {
   3142         case XML_ELEMENT_NODE:
   3143         case XML_ATTRIBUTE_NODE:
   3144 	    if ((node->ns == NULL) ||
   3145 		(node->ns->prefix == NULL))
   3146 		return(xmlStrdup(node->name));
   3147 
   3148 	    ret = xmlStrdup(node->ns->prefix);
   3149 	    ret = xmlStrcat(ret, BAD_CAST ":");
   3150 	    ret = xmlStrcat(ret, node->name);
   3151 	    return(ret);
   3152         case XML_TEXT_NODE:
   3153 	    return(xmlStrdup(BAD_CAST "#text"));
   3154         case XML_CDATA_SECTION_NODE:
   3155 	    return(xmlStrdup(BAD_CAST "#cdata-section"));
   3156         case XML_ENTITY_NODE:
   3157         case XML_ENTITY_REF_NODE:
   3158 	    return(xmlStrdup(node->name));
   3159         case XML_PI_NODE:
   3160 	    return(xmlStrdup(node->name));
   3161         case XML_COMMENT_NODE:
   3162 	    return(xmlStrdup(BAD_CAST "#comment"));
   3163         case XML_DOCUMENT_NODE:
   3164         case XML_HTML_DOCUMENT_NODE:
   3165 #ifdef LIBXML_DOCB_ENABLED
   3166         case XML_DOCB_DOCUMENT_NODE:
   3167 #endif
   3168 	    return(xmlStrdup(BAD_CAST "#document"));
   3169         case XML_DOCUMENT_FRAG_NODE:
   3170 	    return(xmlStrdup(BAD_CAST "#document-fragment"));
   3171         case XML_NOTATION_NODE:
   3172 	    return(xmlStrdup(node->name));
   3173         case XML_DOCUMENT_TYPE_NODE:
   3174         case XML_DTD_NODE:
   3175 	    return(xmlStrdup(node->name));
   3176         case XML_NAMESPACE_DECL: {
   3177 	    xmlNsPtr ns = (xmlNsPtr) node;
   3178 
   3179 	    ret = xmlStrdup(BAD_CAST "xmlns");
   3180 	    if (ns->prefix == NULL)
   3181 		return(ret);
   3182 	    ret = xmlStrcat(ret, BAD_CAST ":");
   3183 	    ret = xmlStrcat(ret, ns->prefix);
   3184 	    return(ret);
   3185 	}
   3186 
   3187         case XML_ELEMENT_DECL:
   3188         case XML_ATTRIBUTE_DECL:
   3189         case XML_ENTITY_DECL:
   3190         case XML_XINCLUDE_START:
   3191         case XML_XINCLUDE_END:
   3192 	    return(NULL);
   3193     }
   3194     return(NULL);
   3195 }
   3196 
   3197 /**
   3198  * xmlTextReaderConstName:
   3199  * @reader:  the xmlTextReaderPtr used
   3200  *
   3201  * The qualified name of the node, equal to Prefix :LocalName.
   3202  *
   3203  * Returns the local name or NULL if not available, the string is
   3204  *         deallocated with the reader.
   3205  */
   3206 const xmlChar *
   3207 xmlTextReaderConstName(xmlTextReaderPtr reader) {
   3208     xmlNodePtr node;
   3209 
   3210     if ((reader == NULL) || (reader->node == NULL))
   3211 	return(NULL);
   3212     if (reader->curnode != NULL)
   3213 	node = reader->curnode;
   3214     else
   3215 	node = reader->node;
   3216     switch (node->type) {
   3217         case XML_ELEMENT_NODE:
   3218         case XML_ATTRIBUTE_NODE:
   3219 	    if ((node->ns == NULL) ||
   3220 		(node->ns->prefix == NULL))
   3221 		return(node->name);
   3222 	    return(CONSTQSTR(node->ns->prefix, node->name));
   3223         case XML_TEXT_NODE:
   3224 	    return(CONSTSTR(BAD_CAST "#text"));
   3225         case XML_CDATA_SECTION_NODE:
   3226 	    return(CONSTSTR(BAD_CAST "#cdata-section"));
   3227         case XML_ENTITY_NODE:
   3228         case XML_ENTITY_REF_NODE:
   3229 	    return(CONSTSTR(node->name));
   3230         case XML_PI_NODE:
   3231 	    return(CONSTSTR(node->name));
   3232         case XML_COMMENT_NODE:
   3233 	    return(CONSTSTR(BAD_CAST "#comment"));
   3234         case XML_DOCUMENT_NODE:
   3235         case XML_HTML_DOCUMENT_NODE:
   3236 #ifdef LIBXML_DOCB_ENABLED
   3237         case XML_DOCB_DOCUMENT_NODE:
   3238 #endif
   3239 	    return(CONSTSTR(BAD_CAST "#document"));
   3240         case XML_DOCUMENT_FRAG_NODE:
   3241 	    return(CONSTSTR(BAD_CAST "#document-fragment"));
   3242         case XML_NOTATION_NODE:
   3243 	    return(CONSTSTR(node->name));
   3244         case XML_DOCUMENT_TYPE_NODE:
   3245         case XML_DTD_NODE:
   3246 	    return(CONSTSTR(node->name));
   3247         case XML_NAMESPACE_DECL: {
   3248 	    xmlNsPtr ns = (xmlNsPtr) node;
   3249 
   3250 	    if (ns->prefix == NULL)
   3251 		return(CONSTSTR(BAD_CAST "xmlns"));
   3252 	    return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
   3253 	}
   3254 
   3255         case XML_ELEMENT_DECL:
   3256         case XML_ATTRIBUTE_DECL:
   3257         case XML_ENTITY_DECL:
   3258         case XML_XINCLUDE_START:
   3259         case XML_XINCLUDE_END:
   3260 	    return(NULL);
   3261     }
   3262     return(NULL);
   3263 }
   3264 
   3265 /**
   3266  * xmlTextReaderPrefix:
   3267  * @reader:  the xmlTextReaderPtr used
   3268  *
   3269  * A shorthand reference to the namespace associated with the node.
   3270  *
   3271  * Returns the prefix or NULL if not available,
   3272  *    if non NULL it need to be freed by the caller.
   3273  */
   3274 xmlChar *
   3275 xmlTextReaderPrefix(xmlTextReaderPtr reader) {
   3276     xmlNodePtr node;
   3277     if ((reader == NULL) || (reader->node == NULL))
   3278 	return(NULL);
   3279     if (reader->curnode != NULL)
   3280 	node = reader->curnode;
   3281     else
   3282 	node = reader->node;
   3283     if (node->type == XML_NAMESPACE_DECL) {
   3284 	xmlNsPtr ns = (xmlNsPtr) node;
   3285 	if (ns->prefix == NULL)
   3286 	    return(NULL);
   3287 	return(xmlStrdup(BAD_CAST "xmlns"));
   3288     }
   3289     if ((node->type != XML_ELEMENT_NODE) &&
   3290 	(node->type != XML_ATTRIBUTE_NODE))
   3291 	return(NULL);
   3292     if ((node->ns != NULL) && (node->ns->prefix != NULL))
   3293 	return(xmlStrdup(node->ns->prefix));
   3294     return(NULL);
   3295 }
   3296 
   3297 /**
   3298  * xmlTextReaderConstPrefix:
   3299  * @reader:  the xmlTextReaderPtr used
   3300  *
   3301  * A shorthand reference to the namespace associated with the node.
   3302  *
   3303  * Returns the prefix or NULL if not available, the string is deallocated
   3304  *         with the reader.
   3305  */
   3306 const xmlChar *
   3307 xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
   3308     xmlNodePtr node;
   3309     if ((reader == NULL) || (reader->node == NULL))
   3310 	return(NULL);
   3311     if (reader->curnode != NULL)
   3312 	node = reader->curnode;
   3313     else
   3314 	node = reader->node;
   3315     if (node->type == XML_NAMESPACE_DECL) {
   3316 	xmlNsPtr ns = (xmlNsPtr) node;
   3317 	if (ns->prefix == NULL)
   3318 	    return(NULL);
   3319 	return(CONSTSTR(BAD_CAST "xmlns"));
   3320     }
   3321     if ((node->type != XML_ELEMENT_NODE) &&
   3322 	(node->type != XML_ATTRIBUTE_NODE))
   3323 	return(NULL);
   3324     if ((node->ns != NULL) && (node->ns->prefix != NULL))
   3325 	return(CONSTSTR(node->ns->prefix));
   3326     return(NULL);
   3327 }
   3328 
   3329 /**
   3330  * xmlTextReaderNamespaceUri:
   3331  * @reader:  the xmlTextReaderPtr used
   3332  *
   3333  * The URI defining the namespace associated with the node.
   3334  *
   3335  * Returns the namespace URI or NULL if not available,
   3336  *    if non NULL it need to be freed by the caller.
   3337  */
   3338 xmlChar *
   3339 xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
   3340     xmlNodePtr node;
   3341     if ((reader == NULL) || (reader->node == NULL))
   3342 	return(NULL);
   3343     if (reader->curnode != NULL)
   3344 	node = reader->curnode;
   3345     else
   3346 	node = reader->node;
   3347     if (node->type == XML_NAMESPACE_DECL)
   3348 	return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
   3349     if ((node->type != XML_ELEMENT_NODE) &&
   3350 	(node->type != XML_ATTRIBUTE_NODE))
   3351 	return(NULL);
   3352     if (node->ns != NULL)
   3353 	return(xmlStrdup(node->ns->href));
   3354     return(NULL);
   3355 }
   3356 
   3357 /**
   3358  * xmlTextReaderConstNamespaceUri:
   3359  * @reader:  the xmlTextReaderPtr used
   3360  *
   3361  * The URI defining the namespace associated with the node.
   3362  *
   3363  * Returns the namespace URI or NULL if not available, the string
   3364  *         will be deallocated with the reader
   3365  */
   3366 const xmlChar *
   3367 xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
   3368     xmlNodePtr node;
   3369     if ((reader == NULL) || (reader->node == NULL))
   3370 	return(NULL);
   3371     if (reader->curnode != NULL)
   3372 	node = reader->curnode;
   3373     else
   3374 	node = reader->node;
   3375     if (node->type == XML_NAMESPACE_DECL)
   3376 	return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
   3377     if ((node->type != XML_ELEMENT_NODE) &&
   3378 	(node->type != XML_ATTRIBUTE_NODE))
   3379 	return(NULL);
   3380     if (node->ns != NULL)
   3381 	return(CONSTSTR(node->ns->href));
   3382     return(NULL);
   3383 }
   3384 
   3385 /**
   3386  * xmlTextReaderBaseUri:
   3387  * @reader:  the xmlTextReaderPtr used
   3388  *
   3389  * The base URI of the node.
   3390  *
   3391  * Returns the base URI or NULL if not available,
   3392  *    if non NULL it need to be freed by the caller.
   3393  */
   3394 xmlChar *
   3395 xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
   3396     if ((reader == NULL) || (reader->node == NULL))
   3397 	return(NULL);
   3398     return(xmlNodeGetBase(NULL, reader->node));
   3399 }
   3400 
   3401 /**
   3402  * xmlTextReaderConstBaseUri:
   3403  * @reader:  the xmlTextReaderPtr used
   3404  *
   3405  * The base URI of the node.
   3406  *
   3407  * Returns the base URI or NULL if not available, the string
   3408  *         will be deallocated with the reader
   3409  */
   3410 const xmlChar *
   3411 xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
   3412     xmlChar *tmp;
   3413     const xmlChar *ret;
   3414 
   3415     if ((reader == NULL) || (reader->node == NULL))
   3416 	return(NULL);
   3417     tmp = xmlNodeGetBase(NULL, reader->node);
   3418     if (tmp == NULL)
   3419         return(NULL);
   3420     ret = CONSTSTR(tmp);
   3421     xmlFree(tmp);
   3422     return(ret);
   3423 }
   3424 
   3425 /**
   3426  * xmlTextReaderDepth:
   3427  * @reader:  the xmlTextReaderPtr used
   3428  *
   3429  * The depth of the node in the tree.
   3430  *
   3431  * Returns the depth or -1 in case of error
   3432  */
   3433 int
   3434 xmlTextReaderDepth(xmlTextReaderPtr reader) {
   3435     if (reader == NULL)
   3436 	return(-1);
   3437     if (reader->node == NULL)
   3438 	return(0);
   3439 
   3440     if (reader->curnode != NULL) {
   3441 	if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
   3442 	    (reader->curnode->type == XML_NAMESPACE_DECL))
   3443 	    return(reader->depth + 1);
   3444 	return(reader->depth + 2);
   3445     }
   3446     return(reader->depth);
   3447 }
   3448 
   3449 /**
   3450  * xmlTextReaderHasAttributes:
   3451  * @reader:  the xmlTextReaderPtr used
   3452  *
   3453  * Whether the node has attributes.
   3454  *
   3455  * Returns 1 if true, 0 if false, and -1 in case or error
   3456  */
   3457 int
   3458 xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
   3459     xmlNodePtr node;
   3460     if (reader == NULL)
   3461 	return(-1);
   3462     if (reader->node == NULL)
   3463 	return(0);
   3464     if (reader->curnode != NULL)
   3465 	node = reader->curnode;
   3466     else
   3467 	node = reader->node;
   3468 
   3469     if ((node->type == XML_ELEMENT_NODE) &&
   3470 	((node->properties != NULL) || (node->nsDef != NULL)))
   3471 	return(1);
   3472     /* TODO: handle the xmlDecl */
   3473     return(0);
   3474 }
   3475 
   3476 /**
   3477  * xmlTextReaderHasValue:
   3478  * @reader:  the xmlTextReaderPtr used
   3479  *
   3480  * Whether the node can have a text value.
   3481  *
   3482  * Returns 1 if true, 0 if false, and -1 in case or error
   3483  */
   3484 int
   3485 xmlTextReaderHasValue(xmlTextReaderPtr reader) {
   3486     xmlNodePtr node;
   3487     if (reader == NULL)
   3488 	return(-1);
   3489     if (reader->node == NULL)
   3490 	return(0);
   3491     if (reader->curnode != NULL)
   3492 	node = reader->curnode;
   3493     else
   3494 	node = reader->node;
   3495 
   3496     switch (node->type) {
   3497         case XML_ATTRIBUTE_NODE:
   3498         case XML_TEXT_NODE:
   3499         case XML_CDATA_SECTION_NODE:
   3500         case XML_PI_NODE:
   3501         case XML_COMMENT_NODE:
   3502         case XML_NAMESPACE_DECL:
   3503 	    return(1);
   3504 	default:
   3505 	    break;
   3506     }
   3507     return(0);
   3508 }
   3509 
   3510 /**
   3511  * xmlTextReaderValue:
   3512  * @reader:  the xmlTextReaderPtr used
   3513  *
   3514  * Provides the text value of the node if present
   3515  *
   3516  * Returns the string or NULL if not available. The result must be deallocated
   3517  *     with xmlFree()
   3518  */
   3519 xmlChar *
   3520 xmlTextReaderValue(xmlTextReaderPtr reader) {
   3521     xmlNodePtr node;
   3522     if (reader == NULL)
   3523 	return(NULL);
   3524     if (reader->node == NULL)
   3525 	return(NULL);
   3526     if (reader->curnode != NULL)
   3527 	node = reader->curnode;
   3528     else
   3529 	node = reader->node;
   3530 
   3531     switch (node->type) {
   3532         case XML_NAMESPACE_DECL:
   3533 	    return(xmlStrdup(((xmlNsPtr) node)->href));
   3534         case XML_ATTRIBUTE_NODE:{
   3535 	    xmlAttrPtr attr = (xmlAttrPtr) node;
   3536 
   3537 	    if (attr->parent != NULL)
   3538 		return (xmlNodeListGetString
   3539 			(attr->parent->doc, attr->children, 1));
   3540 	    else
   3541 		return (xmlNodeListGetString(NULL, attr->children, 1));
   3542 	    break;
   3543 	}
   3544         case XML_TEXT_NODE:
   3545         case XML_CDATA_SECTION_NODE:
   3546         case XML_PI_NODE:
   3547         case XML_COMMENT_NODE:
   3548             if (node->content != NULL)
   3549                 return (xmlStrdup(node->content));
   3550 	default:
   3551 	    break;
   3552     }
   3553     return(NULL);
   3554 }
   3555 
   3556 /**
   3557  * xmlTextReaderConstValue:
   3558  * @reader:  the xmlTextReaderPtr used
   3559  *
   3560  * Provides the text value of the node if present
   3561  *
   3562  * Returns the string or NULL if not available. The result will be
   3563  *     deallocated on the next Read() operation.
   3564  */
   3565 const xmlChar *
   3566 xmlTextReaderConstValue(xmlTextReaderPtr reader) {
   3567     xmlNodePtr node;
   3568     if (reader == NULL)
   3569 	return(NULL);
   3570     if (reader->node == NULL)
   3571 	return(NULL);
   3572     if (reader->curnode != NULL)
   3573 	node = reader->curnode;
   3574     else
   3575 	node = reader->node;
   3576 
   3577     switch (node->type) {
   3578         case XML_NAMESPACE_DECL:
   3579 	    return(((xmlNsPtr) node)->href);
   3580         case XML_ATTRIBUTE_NODE:{
   3581 	    xmlAttrPtr attr = (xmlAttrPtr) node;
   3582 
   3583 	    if ((attr->children != NULL) &&
   3584 	        (attr->children->type == XML_TEXT_NODE) &&
   3585 		(attr->children->next == NULL))
   3586 		return(attr->children->content);
   3587 	    else {
   3588 		if (reader->buffer == NULL)
   3589 		    reader->buffer = xmlBufferCreateSize(100);
   3590 		if (reader->buffer == NULL) {
   3591 		    xmlGenericError(xmlGenericErrorContext,
   3592 				    "xmlTextReaderSetup : malloc failed\n");
   3593 		    return (NULL);
   3594 		}
   3595 	        reader->buffer->use = 0;
   3596 	        xmlNodeBufGetContent(reader->buffer, node);
   3597 		return(reader->buffer->content);
   3598 	    }
   3599 	    break;
   3600 	}
   3601         case XML_TEXT_NODE:
   3602         case XML_CDATA_SECTION_NODE:
   3603         case XML_PI_NODE:
   3604         case XML_COMMENT_NODE:
   3605 	    return(node->content);
   3606 	default:
   3607 	    break;
   3608     }
   3609     return(NULL);
   3610 }
   3611 
   3612 /**
   3613  * xmlTextReaderIsDefault:
   3614  * @reader:  the xmlTextReaderPtr used
   3615  *
   3616  * Whether an Attribute  node was generated from the default value
   3617  * defined in the DTD or schema.
   3618  *
   3619  * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
   3620  */
   3621 int
   3622 xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
   3623     if (reader == NULL)
   3624 	return(-1);
   3625     return(0);
   3626 }
   3627 
   3628 /**
   3629  * xmlTextReaderQuoteChar:
   3630  * @reader:  the xmlTextReaderPtr used
   3631  *
   3632  * The quotation mark character used to enclose the value of an attribute.
   3633  *
   3634  * Returns " or ' and -1 in case of error
   3635  */
   3636 int
   3637 xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
   3638     if (reader == NULL)
   3639 	return(-1);
   3640     /* TODO maybe lookup the attribute value for " first */
   3641     return((int) '"');
   3642 }
   3643 
   3644 /**
   3645  * xmlTextReaderXmlLang:
   3646  * @reader:  the xmlTextReaderPtr used
   3647  *
   3648  * The xml:lang scope within which the node resides.
   3649  *
   3650  * Returns the xml:lang value or NULL if none exists.,
   3651  *    if non NULL it need to be freed by the caller.
   3652  */
   3653 xmlChar *
   3654 xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
   3655     if (reader == NULL)
   3656 	return(NULL);
   3657     if (reader->node == NULL)
   3658 	return(NULL);
   3659     return(xmlNodeGetLang(reader->node));
   3660 }
   3661 
   3662 /**
   3663  * xmlTextReaderConstXmlLang:
   3664  * @reader:  the xmlTextReaderPtr used
   3665  *
   3666  * The xml:lang scope within which the node resides.
   3667  *
   3668  * Returns the xml:lang value or NULL if none exists.
   3669  */
   3670 const xmlChar *
   3671 xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
   3672     xmlChar *tmp;
   3673     const xmlChar *ret;
   3674 
   3675     if (reader == NULL)
   3676 	return(NULL);
   3677     if (reader->node == NULL)
   3678 	return(NULL);
   3679     tmp = xmlNodeGetLang(reader->node);
   3680     if (tmp == NULL)
   3681         return(NULL);
   3682     ret = CONSTSTR(tmp);
   3683     xmlFree(tmp);
   3684     return(ret);
   3685 }
   3686 
   3687 /**
   3688  * xmlTextReaderConstString:
   3689  * @reader:  the xmlTextReaderPtr used
   3690  * @str:  the string to intern.
   3691  *
   3692  * Get an interned string from the reader, allows for example to
   3693  * speedup string name comparisons
   3694  *
   3695  * Returns an interned copy of the string or NULL in case of error. The
   3696  *         string will be deallocated with the reader.
   3697  */
   3698 const xmlChar *
   3699 xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
   3700     if (reader == NULL)
   3701 	return(NULL);
   3702     return(CONSTSTR(str));
   3703 }
   3704 
   3705 /**
   3706  * xmlTextReaderNormalization:
   3707  * @reader:  the xmlTextReaderPtr used
   3708  *
   3709  * The value indicating whether to normalize white space and attribute values.
   3710  * Since attribute value and end of line normalizations are a MUST in the XML
   3711  * specification only the value true is accepted. The broken bahaviour of
   3712  * accepting out of range character entities like &#0; is of course not
   3713  * supported either.
   3714  *
   3715  * Returns 1 or -1 in case of error.
   3716  */
   3717 int
   3718 xmlTextReaderNormalization(xmlTextReaderPtr reader) {
   3719     if (reader == NULL)
   3720 	return(-1);
   3721     return(1);
   3722 }
   3723 
   3724 /************************************************************************
   3725  *									*
   3726  *			Extensions to the base APIs			*
   3727  *									*
   3728  ************************************************************************/
   3729 
   3730 /**
   3731  * xmlTextReaderSetParserProp:
   3732  * @reader:  the xmlTextReaderPtr used
   3733  * @prop:  the xmlParserProperties to set
   3734  * @value:  usually 0 or 1 to (de)activate it
   3735  *
   3736  * Change the parser processing behaviour by changing some of its internal
   3737  * properties. Note that some properties can only be changed before any
   3738  * read has been done.
   3739  *
   3740  * Returns 0 if the call was successful, or -1 in case of error
   3741  */
   3742 int
   3743 xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
   3744     xmlParserProperties p = (xmlParserProperties) prop;
   3745     xmlParserCtxtPtr ctxt;
   3746 
   3747     if ((reader == NULL) || (reader->ctxt == NULL))
   3748 	return(-1);
   3749     ctxt = reader->ctxt;
   3750 
   3751     switch (p) {
   3752         case XML_PARSER_LOADDTD:
   3753 	    if (value != 0) {
   3754 		if (ctxt->loadsubset == 0) {
   3755 		    if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
   3756 			return(-1);
   3757 		    ctxt->loadsubset = XML_DETECT_IDS;
   3758 		}
   3759 	    } else {
   3760 		ctxt->loadsubset = 0;
   3761 	    }
   3762 	    return(0);
   3763         case XML_PARSER_DEFAULTATTRS:
   3764 	    if (value != 0) {
   3765 		ctxt->loadsubset |= XML_COMPLETE_ATTRS;
   3766 	    } else {
   3767 		if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
   3768 		    ctxt->loadsubset -= XML_COMPLETE_ATTRS;
   3769 	    }
   3770 	    return(0);
   3771         case XML_PARSER_VALIDATE:
   3772 	    if (value != 0) {
   3773 		ctxt->validate = 1;
   3774 		reader->validate = XML_TEXTREADER_VALIDATE_DTD;
   3775 	    } else {
   3776 		ctxt->validate = 0;
   3777 	    }
   3778 	    return(0);
   3779         case XML_PARSER_SUBST_ENTITIES:
   3780 	    if (value != 0) {
   3781 		ctxt->replaceEntities = 1;
   3782 	    } else {
   3783 		ctxt->replaceEntities = 0;
   3784 	    }
   3785 	    return(0);
   3786     }
   3787     return(-1);
   3788 }
   3789 
   3790 /**
   3791  * xmlTextReaderGetParserProp:
   3792  * @reader:  the xmlTextReaderPtr used
   3793  * @prop:  the xmlParserProperties to get
   3794  *
   3795  * Read the parser internal property.
   3796  *
   3797  * Returns the value, usually 0 or 1, or -1 in case of error.
   3798  */
   3799 int
   3800 xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
   3801     xmlParserProperties p = (xmlParserProperties) prop;
   3802     xmlParserCtxtPtr ctxt;
   3803 
   3804     if ((reader == NULL) || (reader->ctxt == NULL))
   3805 	return(-1);
   3806     ctxt = reader->ctxt;
   3807 
   3808     switch (p) {
   3809         case XML_PARSER_LOADDTD:
   3810 	    if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
   3811 		return(1);
   3812 	    return(0);
   3813         case XML_PARSER_DEFAULTATTRS:
   3814 	    if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
   3815 		return(1);
   3816 	    return(0);
   3817         case XML_PARSER_VALIDATE:
   3818 	    return(reader->validate);
   3819 	case XML_PARSER_SUBST_ENTITIES:
   3820 	    return(ctxt->replaceEntities);
   3821     }
   3822     return(-1);
   3823 }
   3824 
   3825 
   3826 /**
   3827  * xmlTextReaderGetParserLineNumber:
   3828  * @reader: the user data (XML reader context)
   3829  *
   3830  * Provide the line number of the current parsing point.
   3831  *
   3832  * Returns an int or 0 if not available
   3833  */
   3834 int
   3835 xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
   3836 {
   3837     if ((reader == NULL) || (reader->ctxt == NULL) ||
   3838         (reader->ctxt->input == NULL)) {
   3839         return (0);
   3840     }
   3841     return (reader->ctxt->input->line);
   3842 }
   3843 
   3844 /**
   3845  * xmlTextReaderGetParserColumnNumber:
   3846  * @reader: the user data (XML reader context)
   3847  *
   3848  * Provide the column number of the current parsing point.
   3849  *
   3850  * Returns an int or 0 if not available
   3851  */
   3852 int
   3853 xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
   3854 {
   3855     if ((reader == NULL) || (reader->ctxt == NULL) ||
   3856         (reader->ctxt->input == NULL)) {
   3857         return (0);
   3858     }
   3859     return (reader->ctxt->input->col);
   3860 }
   3861 
   3862 /**
   3863  * xmlTextReaderCurrentNode:
   3864  * @reader:  the xmlTextReaderPtr used
   3865  *
   3866  * Hacking interface allowing to get the xmlNodePtr correponding to the
   3867  * current node being accessed by the xmlTextReader. This is dangerous
   3868  * because the underlying node may be destroyed on the next Reads.
   3869  *
   3870  * Returns the xmlNodePtr or NULL in case of error.
   3871  */
   3872 xmlNodePtr
   3873 xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
   3874     if (reader == NULL)
   3875 	return(NULL);
   3876 
   3877     if (reader->curnode != NULL)
   3878 	return(reader->curnode);
   3879     return(reader->node);
   3880 }
   3881 
   3882 /**
   3883  * xmlTextReaderPreserve:
   3884  * @reader:  the xmlTextReaderPtr used
   3885  *
   3886  * This tells the XML Reader to preserve the current node.
   3887  * The caller must also use xmlTextReaderCurrentDoc() to
   3888  * keep an handle on the resulting document once parsing has finished
   3889  *
   3890  * Returns the xmlNodePtr or NULL in case of error.
   3891  */
   3892 xmlNodePtr
   3893 xmlTextReaderPreserve(xmlTextReaderPtr reader) {
   3894     xmlNodePtr cur, parent;
   3895 
   3896     if (reader == NULL)
   3897 	return(NULL);
   3898 
   3899     if (reader->curnode != NULL)
   3900         cur = reader->curnode;
   3901     else
   3902         cur = reader->node;
   3903     if (cur == NULL)
   3904         return(NULL);
   3905 
   3906     if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
   3907 	cur->extra |= NODE_IS_PRESERVED;
   3908 	cur->extra |= NODE_IS_SPRESERVED;
   3909     }
   3910     reader->preserves++;
   3911 
   3912     parent = cur->parent;;
   3913     while (parent != NULL) {
   3914         if (parent->type == XML_ELEMENT_NODE)
   3915 	    parent->extra |= NODE_IS_PRESERVED;
   3916 	parent = parent->parent;
   3917     }
   3918     return(cur);
   3919 }
   3920 
   3921 #ifdef LIBXML_PATTERN_ENABLED
   3922 /**
   3923  * xmlTextReaderPreservePattern:
   3924  * @reader:  the xmlTextReaderPtr used
   3925  * @pattern:  an XPath subset pattern
   3926  * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
   3927  *
   3928  * This tells the XML Reader to preserve all nodes matched by the
   3929  * pattern. The caller must also use xmlTextReaderCurrentDoc() to
   3930  * keep an handle on the resulting document once parsing has finished
   3931  *
   3932  * Returns a positive number in case of success and -1 in case of error
   3933  */
   3934 int
   3935 xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
   3936                              const xmlChar **namespaces)
   3937 {
   3938     xmlPatternPtr comp;
   3939 
   3940     if ((reader == NULL) || (pattern == NULL))
   3941 	return(-1);
   3942 
   3943     comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
   3944     if (comp == NULL)
   3945         return(-1);
   3946 
   3947     if (reader->patternMax <= 0) {
   3948 	reader->patternMax = 4;
   3949 	reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
   3950 					      sizeof(reader->patternTab[0]));
   3951         if (reader->patternTab == NULL) {
   3952             xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
   3953             return (-1);
   3954         }
   3955     }
   3956     if (reader->patternNr >= reader->patternMax) {
   3957         xmlPatternPtr *tmp;
   3958         reader->patternMax *= 2;
   3959 	tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
   3960                                       reader->patternMax *
   3961                                       sizeof(reader->patternTab[0]));
   3962         if (tmp == NULL) {
   3963             xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
   3964 	    reader->patternMax /= 2;
   3965             return (-1);
   3966         }
   3967 	reader->patternTab = tmp;
   3968     }
   3969     reader->patternTab[reader->patternNr] = comp;
   3970     return(reader->patternNr++);
   3971 }
   3972 #endif
   3973 
   3974 /**
   3975  * xmlTextReaderCurrentDoc:
   3976  * @reader:  the xmlTextReaderPtr used
   3977  *
   3978  * Hacking interface allowing to get the xmlDocPtr correponding to the
   3979  * current document being accessed by the xmlTextReader.
   3980  * NOTE: as a result of this call, the reader will not destroy the
   3981  *       associated XML document and calling xmlFreeDoc() on the result
   3982  *       is needed once the reader parsing has finished.
   3983  *
   3984  * Returns the xmlDocPtr or NULL in case of error.
   3985  */
   3986 xmlDocPtr
   3987 xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
   3988     if (reader == NULL)
   3989 	return(NULL);
   3990     if (reader->doc != NULL)
   3991         return(reader->doc);
   3992     if ((reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL))
   3993 	return(NULL);
   3994 
   3995     reader->preserve = 1;
   3996     return(reader->ctxt->myDoc);
   3997 }
   3998 
   3999 #ifdef LIBXML_SCHEMAS_ENABLED
   4000 static char *xmlTextReaderBuildMessage(const char *msg, va_list ap);
   4001 
   4002 static void XMLCDECL
   4003 xmlTextReaderValidityError(void *ctxt, const char *msg, ...);
   4004 
   4005 static void XMLCDECL
   4006 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...);
   4007 
   4008 static void XMLCDECL
   4009 xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
   4010 {
   4011     xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
   4012 
   4013     char *str;
   4014 
   4015     va_list ap;
   4016 
   4017     va_start(ap, msg);
   4018     str = xmlTextReaderBuildMessage(msg, ap);
   4019     if (!reader->errorFunc) {
   4020         xmlTextReaderValidityError(ctx, "%s", str);
   4021     } else {
   4022         reader->errorFunc(reader->errorFuncArg, str,
   4023                           XML_PARSER_SEVERITY_VALIDITY_ERROR,
   4024                           NULL /* locator */ );
   4025     }
   4026     if (str != NULL)
   4027         xmlFree(str);
   4028     va_end(ap);
   4029 }
   4030 
   4031 static void XMLCDECL
   4032 xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
   4033 {
   4034     xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
   4035 
   4036     char *str;
   4037 
   4038     va_list ap;
   4039 
   4040     va_start(ap, msg);
   4041     str = xmlTextReaderBuildMessage(msg, ap);
   4042     if (!reader->errorFunc) {
   4043         xmlTextReaderValidityWarning(ctx, "%s", str);
   4044     } else {
   4045         reader->errorFunc(reader->errorFuncArg, str,
   4046                           XML_PARSER_SEVERITY_VALIDITY_WARNING,
   4047                           NULL /* locator */ );
   4048     }
   4049     if (str != NULL)
   4050         xmlFree(str);
   4051     va_end(ap);
   4052 }
   4053 
   4054 static void
   4055   xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
   4056 
   4057 static void
   4058 xmlTextReaderValidityStructuredRelay(void *userData, xmlErrorPtr error)
   4059 {
   4060     xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
   4061 
   4062     if (reader->sErrorFunc) {
   4063         reader->sErrorFunc(reader->errorFuncArg, error);
   4064     } else {
   4065         xmlTextReaderStructuredError(reader, error);
   4066     }
   4067 }
   4068 /**
   4069  * xmlTextReaderRelaxNGSetSchema:
   4070  * @reader:  the xmlTextReaderPtr used
   4071  * @schema:  a precompiled RelaxNG schema
   4072  *
   4073  * Use RelaxNG to validate the document as it is processed.
   4074  * Activation is only possible before the first Read().
   4075  * if @schema is NULL, then RelaxNG validation is desactivated.
   4076  @ The @schema should not be freed until the reader is deallocated
   4077  * or its use has been deactivated.
   4078  *
   4079  * Returns 0 in case the RelaxNG validation could be (des)activated and
   4080  *         -1 in case of error.
   4081  */
   4082 int
   4083 xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
   4084     if (reader == NULL)
   4085         return(-1);
   4086     if (schema == NULL) {
   4087         if (reader->rngSchemas != NULL) {
   4088 	    xmlRelaxNGFree(reader->rngSchemas);
   4089 	    reader->rngSchemas = NULL;
   4090 	}
   4091         if (reader->rngValidCtxt != NULL) {
   4092 	    xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
   4093 	    reader->rngValidCtxt = NULL;
   4094         }
   4095 	return(0);
   4096     }
   4097     if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
   4098 	return(-1);
   4099     if (reader->rngSchemas != NULL) {
   4100 	xmlRelaxNGFree(reader->rngSchemas);
   4101 	reader->rngSchemas = NULL;
   4102     }
   4103     if (reader->rngValidCtxt != NULL) {
   4104 	xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
   4105 	reader->rngValidCtxt = NULL;
   4106     }
   4107     reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
   4108     if (reader->rngValidCtxt == NULL)
   4109         return(-1);
   4110     if (reader->errorFunc != NULL) {
   4111 	xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
   4112 			xmlTextReaderValidityErrorRelay,
   4113 			xmlTextReaderValidityWarningRelay,
   4114 			reader);
   4115     }
   4116 	if (reader->sErrorFunc != NULL) {
   4117 		xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
   4118 			xmlTextReaderValidityStructuredRelay,
   4119 			reader);
   4120     }
   4121     reader->rngValidErrors = 0;
   4122     reader->rngFullNode = NULL;
   4123     reader->validate = XML_TEXTREADER_VALIDATE_RNG;
   4124     return(0);
   4125 }
   4126 
   4127 /**
   4128  * xmlTextReaderSetSchema:
   4129  * @reader:  the xmlTextReaderPtr used
   4130  * @schema:  a precompiled Schema schema
   4131  *
   4132  * Use XSD Schema to validate the document as it is processed.
   4133  * Activation is only possible before the first Read().
   4134  * if @schema is NULL, then Schema validation is desactivated.
   4135  @ The @schema should not be freed until the reader is deallocated
   4136  * or its use has been deactivated.
   4137  *
   4138  * Returns 0 in case the Schema validation could be (des)activated and
   4139  *         -1 in case of error.
   4140  */
   4141 int
   4142 xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
   4143     if (reader == NULL)
   4144         return(-1);
   4145     if (schema == NULL) {
   4146 	if (reader->xsdPlug != NULL) {
   4147 	    xmlSchemaSAXUnplug(reader->xsdPlug);
   4148 	    reader->xsdPlug = NULL;
   4149 	}
   4150         if (reader->xsdValidCtxt != NULL) {
   4151 	    if (! reader->xsdPreserveCtxt)
   4152 		xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
   4153 	    reader->xsdValidCtxt = NULL;
   4154         }
   4155 	reader->xsdPreserveCtxt = 0;
   4156         if (reader->xsdSchemas != NULL) {
   4157 	    xmlSchemaFree(reader->xsdSchemas);
   4158 	    reader->xsdSchemas = NULL;
   4159 	}
   4160 	return(0);
   4161     }
   4162     if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
   4163 	return(-1);
   4164     if (reader->xsdPlug != NULL) {
   4165 	xmlSchemaSAXUnplug(reader->xsdPlug);
   4166 	reader->xsdPlug = NULL;
   4167     }
   4168     if (reader->xsdValidCtxt != NULL) {
   4169 	if (! reader->xsdPreserveCtxt)
   4170 	    xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
   4171 	reader->xsdValidCtxt = NULL;
   4172     }
   4173     reader->xsdPreserveCtxt = 0;
   4174     if (reader->xsdSchemas != NULL) {
   4175 	xmlSchemaFree(reader->xsdSchemas);
   4176 	reader->xsdSchemas = NULL;
   4177     }
   4178     reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
   4179     if (reader->xsdValidCtxt == NULL) {
   4180 	xmlSchemaFree(reader->xsdSchemas);
   4181 	reader->xsdSchemas = NULL;
   4182         return(-1);
   4183     }
   4184     reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
   4185                                        &(reader->ctxt->sax),
   4186 				       &(reader->ctxt->userData));
   4187     if (reader->xsdPlug == NULL) {
   4188 	xmlSchemaFree(reader->xsdSchemas);
   4189 	reader->xsdSchemas = NULL;
   4190 	xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
   4191 	reader->xsdValidCtxt = NULL;
   4192 	return(-1);
   4193     }
   4194     if (reader->errorFunc != NULL) {
   4195 	xmlSchemaSetValidErrors(reader->xsdValidCtxt,
   4196 			xmlTextReaderValidityErrorRelay,
   4197 			xmlTextReaderValidityWarningRelay,
   4198 			reader);
   4199     }
   4200 	if (reader->sErrorFunc != NULL) {
   4201 		xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
   4202 			xmlTextReaderValidityStructuredRelay,
   4203 			reader);
   4204     }
   4205     reader->xsdValidErrors = 0;
   4206     reader->validate = XML_TEXTREADER_VALIDATE_XSD;
   4207     return(0);
   4208 }
   4209 
   4210 /**
   4211  * xmlTextReaderRelaxNGValidate:
   4212  * @reader:  the xmlTextReaderPtr used
   4213  * @rng:  the path to a RelaxNG schema or NULL
   4214  *
   4215  * Use RelaxNG to validate the document as it is processed.
   4216  * Activation is only possible before the first Read().
   4217  * if @rng is NULL, then RelaxNG validation is deactivated.
   4218  *
   4219  * Returns 0 in case the RelaxNG validation could be (de)activated and
   4220  *         -1 in case of error.
   4221  */
   4222 int
   4223 xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
   4224     xmlRelaxNGParserCtxtPtr ctxt;
   4225 
   4226     if (reader == NULL)
   4227         return(-1);
   4228 
   4229     if (rng == NULL) {
   4230         if (reader->rngValidCtxt != NULL) {
   4231 	    xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
   4232 	    reader->rngValidCtxt = NULL;
   4233         }
   4234         if (reader->rngSchemas != NULL) {
   4235 	    xmlRelaxNGFree(reader->rngSchemas);
   4236 	    reader->rngSchemas = NULL;
   4237 	}
   4238 	return(0);
   4239     }
   4240     if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
   4241 	return(-1);
   4242     if (reader->rngSchemas != NULL) {
   4243 	xmlRelaxNGFree(reader->rngSchemas);
   4244 	reader->rngSchemas = NULL;
   4245     }
   4246     if (reader->rngValidCtxt != NULL) {
   4247 	xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
   4248 	reader->rngValidCtxt = NULL;
   4249     }
   4250     ctxt = xmlRelaxNGNewParserCtxt(rng);
   4251     if (reader->errorFunc != NULL) {
   4252 	xmlRelaxNGSetParserErrors(ctxt,
   4253 			 xmlTextReaderValidityErrorRelay,
   4254 			 xmlTextReaderValidityWarningRelay,
   4255 			 reader);
   4256     }
   4257     if (reader->sErrorFunc != NULL) {
   4258 	xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
   4259 			xmlTextReaderValidityStructuredRelay,
   4260 			reader);
   4261     }
   4262     reader->rngSchemas = xmlRelaxNGParse(ctxt);
   4263     xmlRelaxNGFreeParserCtxt(ctxt);
   4264     if (reader->rngSchemas == NULL)
   4265         return(-1);
   4266     reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
   4267     if (reader->rngValidCtxt == NULL) {
   4268 	xmlRelaxNGFree(reader->rngSchemas);
   4269 	reader->rngSchemas = NULL;
   4270         return(-1);
   4271     }
   4272     if (reader->errorFunc != NULL) {
   4273 	xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
   4274 			 xmlTextReaderValidityErrorRelay,
   4275 			 xmlTextReaderValidityWarningRelay,
   4276 			 reader);
   4277     }
   4278 	if (reader->sErrorFunc != NULL) {
   4279 		xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
   4280 			xmlTextReaderValidityStructuredRelay,
   4281 			reader);
   4282     }
   4283     reader->rngValidErrors = 0;
   4284     reader->rngFullNode = NULL;
   4285     reader->validate = XML_TEXTREADER_VALIDATE_RNG;
   4286     return(0);
   4287 }
   4288 
   4289 /**
   4290  * xmlTextReaderSchemaValidateInternal:
   4291  * @reader:  the xmlTextReaderPtr used
   4292  * @xsd:  the path to a W3C XSD schema or NULL
   4293  * @ctxt: the XML Schema validation context or NULL
   4294  * @options: options (not used yet)
   4295  *
   4296  * Validate the document as it is processed using XML Schema.
   4297  * Activation is only possible before the first Read().
   4298  * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated.
   4299  *
   4300  * Returns 0 in case the schemas validation could be (de)activated and
   4301  *         -1 in case of error.
   4302  */
   4303 static int
   4304 xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
   4305 				    const char *xsd,
   4306 				    xmlSchemaValidCtxtPtr ctxt,
   4307 				    int options ATTRIBUTE_UNUSED)
   4308 {
   4309     if (reader == NULL)
   4310         return(-1);
   4311 
   4312     if ((xsd != NULL) && (ctxt != NULL))
   4313 	return(-1);
   4314 
   4315     if (((xsd != NULL) || (ctxt != NULL)) &&
   4316 	((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
   4317         (reader->ctxt == NULL)))
   4318 	return(-1);
   4319 
   4320     /* Cleanup previous validation stuff. */
   4321     if (reader->xsdPlug != NULL) {
   4322 	xmlSchemaSAXUnplug(reader->xsdPlug);
   4323 	reader->xsdPlug = NULL;
   4324     }
   4325     if (reader->xsdValidCtxt != NULL) {
   4326 	if (! reader->xsdPreserveCtxt)
   4327 	    xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
   4328 	reader->xsdValidCtxt = NULL;
   4329     }
   4330     reader->xsdPreserveCtxt = 0;
   4331     if (reader->xsdSchemas != NULL) {
   4332 	xmlSchemaFree(reader->xsdSchemas);
   4333 	reader->xsdSchemas = NULL;
   4334     }
   4335 
   4336     if ((xsd == NULL) && (ctxt == NULL)) {
   4337 	/* We just want to deactivate the validation, so get out. */
   4338 	return(0);
   4339     }
   4340 
   4341     if (xsd != NULL) {
   4342 	xmlSchemaParserCtxtPtr pctxt;
   4343 	/* Parse the schema and create validation environment. */
   4344 	pctxt = xmlSchemaNewParserCtxt(xsd);
   4345 	if (reader->errorFunc != NULL) {
   4346 	    xmlSchemaSetParserErrors(pctxt,
   4347 		xmlTextReaderValidityErrorRelay,
   4348 		xmlTextReaderValidityWarningRelay,
   4349 		reader);
   4350 	}
   4351 	reader->xsdSchemas = xmlSchemaParse(pctxt);
   4352 	xmlSchemaFreeParserCtxt(pctxt);
   4353 	if (reader->xsdSchemas == NULL)
   4354 	    return(-1);
   4355 	reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
   4356 	if (reader->xsdValidCtxt == NULL) {
   4357 	    xmlSchemaFree(reader->xsdSchemas);
   4358 	    reader->xsdSchemas = NULL;
   4359 	    return(-1);
   4360 	}
   4361 	reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
   4362 	    &(reader->ctxt->sax),
   4363 	    &(reader->ctxt->userData));
   4364 	if (reader->xsdPlug == NULL) {
   4365 	    xmlSchemaFree(reader->xsdSchemas);
   4366 	    reader->xsdSchemas = NULL;
   4367 	    xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
   4368 	    reader->xsdValidCtxt = NULL;
   4369 	    return(-1);
   4370 	}
   4371     } else {
   4372 	/* Use the given validation context. */
   4373 	reader->xsdValidCtxt = ctxt;
   4374 	reader->xsdPreserveCtxt = 1;
   4375 	reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
   4376 	    &(reader->ctxt->sax),
   4377 	    &(reader->ctxt->userData));
   4378 	if (reader->xsdPlug == NULL) {
   4379 	    reader->xsdValidCtxt = NULL;
   4380 	    reader->xsdPreserveCtxt = 0;
   4381 	    return(-1);
   4382 	}
   4383     }
   4384     /*
   4385     * Redirect the validation context's error channels to use
   4386     * the reader channels.
   4387     * TODO: In case the user provides the validation context we
   4388     *   could make this redirection optional.
   4389     */
   4390     if (reader->errorFunc != NULL) {
   4391 	xmlSchemaSetValidErrors(reader->xsdValidCtxt,
   4392 			 xmlTextReaderValidityErrorRelay,
   4393 			 xmlTextReaderValidityWarningRelay,
   4394 			 reader);
   4395     }
   4396 	if (reader->sErrorFunc != NULL) {
   4397 		xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
   4398 			xmlTextReaderValidityStructuredRelay,
   4399 			reader);
   4400     }
   4401     reader->xsdValidErrors = 0;
   4402     reader->validate = XML_TEXTREADER_VALIDATE_XSD;
   4403     return(0);
   4404 }
   4405 
   4406 /**
   4407  * xmlTextReaderSchemaValidateCtxt:
   4408  * @reader:  the xmlTextReaderPtr used
   4409  * @ctxt: the XML Schema validation context or NULL
   4410  * @options: options (not used yet)
   4411  *
   4412  * Use W3C XSD schema context to validate the document as it is processed.
   4413  * Activation is only possible before the first Read().
   4414  * If @ctxt is NULL, then XML Schema validation is deactivated.
   4415  *
   4416  * Returns 0 in case the schemas validation could be (de)activated and
   4417  *         -1 in case of error.
   4418  */
   4419 int
   4420 xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,
   4421 				    xmlSchemaValidCtxtPtr ctxt,
   4422 				    int options)
   4423 {
   4424     return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options));
   4425 }
   4426 
   4427 /**
   4428  * xmlTextReaderSchemaValidate:
   4429  * @reader:  the xmlTextReaderPtr used
   4430  * @xsd:  the path to a W3C XSD schema or NULL
   4431  *
   4432  * Use W3C XSD schema to validate the document as it is processed.
   4433  * Activation is only possible before the first Read().
   4434  * If @xsd is NULL, then XML Schema validation is deactivated.
   4435  *
   4436  * Returns 0 in case the schemas validation could be (de)activated and
   4437  *         -1 in case of error.
   4438  */
   4439 int
   4440 xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd)
   4441 {
   4442     return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));
   4443 }
   4444 #endif
   4445 
   4446 /**
   4447  * xmlTextReaderIsNamespaceDecl:
   4448  * @reader: the xmlTextReaderPtr used
   4449  *
   4450  * Determine whether the current node is a namespace declaration
   4451  * rather than a regular attribute.
   4452  *
   4453  * Returns 1 if the current node is a namespace declaration, 0 if it
   4454  * is a regular attribute or other type of node, or -1 in case of
   4455  * error.
   4456  */
   4457 int
   4458 xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
   4459     xmlNodePtr node;
   4460     if (reader == NULL)
   4461 	return(-1);
   4462     if (reader->node == NULL)
   4463 	return(-1);
   4464     if (reader->curnode != NULL)
   4465 	node = reader->curnode;
   4466     else
   4467 	node = reader->node;
   4468 
   4469     if (XML_NAMESPACE_DECL == node->type)
   4470 	return(1);
   4471     else
   4472 	return(0);
   4473 }
   4474 
   4475 /**
   4476  * xmlTextReaderConstXmlVersion:
   4477  * @reader:  the xmlTextReaderPtr used
   4478  *
   4479  * Determine the XML version of the document being read.
   4480  *
   4481  * Returns a string containing the XML version of the document or NULL
   4482  * in case of error.  The string is deallocated with the reader.
   4483  */
   4484 const xmlChar *
   4485 xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
   4486     xmlDocPtr doc = NULL;
   4487     if (reader == NULL)
   4488 	return(NULL);
   4489     if (reader->doc != NULL)
   4490         doc = reader->doc;
   4491     else if (reader->ctxt != NULL)
   4492 	doc = reader->ctxt->myDoc;
   4493     if (doc == NULL)
   4494 	return(NULL);
   4495 
   4496     if (doc->version == NULL)
   4497 	return(NULL);
   4498     else
   4499       return(CONSTSTR(doc->version));
   4500 }
   4501 
   4502 /**
   4503  * xmlTextReaderStandalone:
   4504  * @reader:  the xmlTextReaderPtr used
   4505  *
   4506  * Determine the standalone status of the document being read.
   4507  *
   4508  * Returns 1 if the document was declared to be standalone, 0 if it
   4509  * was declared to be not standalone, or -1 if the document did not
   4510  * specify its standalone status or in case of error.
   4511  */
   4512 int
   4513 xmlTextReaderStandalone(xmlTextReaderPtr reader) {
   4514     xmlDocPtr doc = NULL;
   4515     if (reader == NULL)
   4516 	return(-1);
   4517     if (reader->doc != NULL)
   4518         doc = reader->doc;
   4519     else if (reader->ctxt != NULL)
   4520 	doc = reader->ctxt->myDoc;
   4521     if (doc == NULL)
   4522 	return(-1);
   4523 
   4524     return(doc->standalone);
   4525 }
   4526 
   4527 /************************************************************************
   4528  *									*
   4529  *			Error Handling Extensions                       *
   4530  *									*
   4531  ************************************************************************/
   4532 
   4533 /* helper to build a xmlMalloc'ed string from a format and va_list */
   4534 static char *
   4535 xmlTextReaderBuildMessage(const char *msg, va_list ap) {
   4536     int size = 0;
   4537     int chars;
   4538     char *larger;
   4539     char *str = NULL;
   4540     va_list aq;
   4541 
   4542     while (1) {
   4543         VA_COPY(aq, ap);
   4544         chars = vsnprintf(str, size, msg, aq);
   4545         va_end(aq);
   4546         if (chars < 0) {
   4547 	    xmlGenericError(xmlGenericErrorContext, "vsnprintf failed !\n");
   4548 	    if (str)
   4549 		xmlFree(str);
   4550 	    return NULL;
   4551 	}
   4552 	if ((chars < size) || (size == MAX_ERR_MSG_SIZE))
   4553             break;
   4554         if (chars < MAX_ERR_MSG_SIZE)
   4555 	size = chars + 1;
   4556 	else
   4557 		size = MAX_ERR_MSG_SIZE;
   4558         if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
   4559 	    xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
   4560 	    if (str)
   4561                 xmlFree(str);
   4562             return NULL;
   4563         }
   4564         str = larger;
   4565     }
   4566 
   4567     return str;
   4568 }
   4569 
   4570 /**
   4571  * xmlTextReaderLocatorLineNumber:
   4572  * @locator: the xmlTextReaderLocatorPtr used
   4573  *
   4574  * Obtain the line number for the given locator.
   4575  *
   4576  * Returns the line number or -1 in case of error.
   4577  */
   4578 int
   4579 xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
   4580     /* we know that locator is a xmlParserCtxtPtr */
   4581     xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
   4582     int ret = -1;
   4583 
   4584     if (locator == NULL)
   4585         return(-1);
   4586     if (ctx->node != NULL) {
   4587 	ret = xmlGetLineNo(ctx->node);
   4588     }
   4589     else {
   4590 	/* inspired from error.c */
   4591 	xmlParserInputPtr input;
   4592 	input = ctx->input;
   4593 	if ((input->filename == NULL) && (ctx->inputNr > 1))
   4594 	    input = ctx->inputTab[ctx->inputNr - 2];
   4595 	if (input != NULL) {
   4596 	    ret = input->line;
   4597 	}
   4598 	else {
   4599 	    ret = -1;
   4600 	}
   4601     }
   4602 
   4603     return ret;
   4604 }
   4605 
   4606 /**
   4607  * xmlTextReaderLocatorBaseURI:
   4608  * @locator: the xmlTextReaderLocatorPtr used
   4609  *
   4610  * Obtain the base URI for the given locator.
   4611  *
   4612  * Returns the base URI or NULL in case of error,
   4613  *    if non NULL it need to be freed by the caller.
   4614  */
   4615 xmlChar *
   4616 xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
   4617     /* we know that locator is a xmlParserCtxtPtr */
   4618     xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
   4619     xmlChar *ret = NULL;
   4620 
   4621     if (locator == NULL)
   4622         return(NULL);
   4623     if (ctx->node != NULL) {
   4624 	ret = xmlNodeGetBase(NULL,ctx->node);
   4625     }
   4626     else {
   4627 	/* inspired from error.c */
   4628 	xmlParserInputPtr input;
   4629 	input = ctx->input;
   4630 	if ((input->filename == NULL) && (ctx->inputNr > 1))
   4631 	    input = ctx->inputTab[ctx->inputNr - 2];
   4632 	if (input != NULL) {
   4633 	    ret = xmlStrdup(BAD_CAST input->filename);
   4634 	}
   4635 	else {
   4636 	    ret = NULL;
   4637 	}
   4638     }
   4639 
   4640     return ret;
   4641 }
   4642 
   4643 static void
   4644 xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity,
   4645                           char *str)
   4646 {
   4647     xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
   4648 
   4649     xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
   4650 
   4651     if (str != NULL) {
   4652         if (reader->errorFunc)
   4653             reader->errorFunc(reader->errorFuncArg, str, severity,
   4654                               (xmlTextReaderLocatorPtr) ctx);
   4655         xmlFree(str);
   4656     }
   4657 }
   4658 
   4659 static void
   4660 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error)
   4661 {
   4662     xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
   4663 
   4664     xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
   4665 
   4666     if (error && reader->sErrorFunc) {
   4667         reader->sErrorFunc(reader->errorFuncArg, (xmlErrorPtr) error);
   4668     }
   4669 }
   4670 
   4671 static void XMLCDECL
   4672 xmlTextReaderError(void *ctxt, const char *msg, ...)
   4673 {
   4674     va_list ap;
   4675 
   4676     va_start(ap, msg);
   4677     xmlTextReaderGenericError(ctxt,
   4678                               XML_PARSER_SEVERITY_ERROR,
   4679                               xmlTextReaderBuildMessage(msg, ap));
   4680     va_end(ap);
   4681 
   4682 }
   4683 
   4684 static void XMLCDECL
   4685 xmlTextReaderWarning(void *ctxt, const char *msg, ...)
   4686 {
   4687     va_list ap;
   4688 
   4689     va_start(ap, msg);
   4690     xmlTextReaderGenericError(ctxt,
   4691                               XML_PARSER_SEVERITY_WARNING,
   4692                               xmlTextReaderBuildMessage(msg, ap));
   4693     va_end(ap);
   4694 }
   4695 
   4696 static void XMLCDECL
   4697 xmlTextReaderValidityError(void *ctxt, const char *msg, ...)
   4698 {
   4699     va_list ap;
   4700 
   4701     int len = xmlStrlen((const xmlChar *) msg);
   4702 
   4703     if ((len > 1) && (msg[len - 2] != ':')) {
   4704         /*
   4705          * some callbacks only report locator information:
   4706          * skip them (mimicking behaviour in error.c)
   4707          */
   4708         va_start(ap, msg);
   4709         xmlTextReaderGenericError(ctxt,
   4710                                   XML_PARSER_SEVERITY_VALIDITY_ERROR,
   4711                                   xmlTextReaderBuildMessage(msg, ap));
   4712         va_end(ap);
   4713     }
   4714 }
   4715 
   4716 static void XMLCDECL
   4717 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...)
   4718 {
   4719     va_list ap;
   4720 
   4721     int len = xmlStrlen((const xmlChar *) msg);
   4722 
   4723     if ((len != 0) && (msg[len - 1] != ':')) {
   4724         /*
   4725          * some callbacks only report locator information:
   4726          * skip them (mimicking behaviour in error.c)
   4727          */
   4728         va_start(ap, msg);
   4729         xmlTextReaderGenericError(ctxt,
   4730                                   XML_PARSER_SEVERITY_VALIDITY_WARNING,
   4731                                   xmlTextReaderBuildMessage(msg, ap));
   4732         va_end(ap);
   4733     }
   4734 }
   4735 
   4736 /**
   4737  * xmlTextReaderSetErrorHandler:
   4738  * @reader:  the xmlTextReaderPtr used
   4739  * @f:	the callback function to call on error and warnings
   4740  * @arg:    a user argument to pass to the callback function
   4741  *
   4742  * Register a callback function that will be called on error and warnings.
   4743  *
   4744  * If @f is NULL, the default error and warning handlers are restored.
   4745  */
   4746 void
   4747 xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
   4748                              xmlTextReaderErrorFunc f, void *arg)
   4749 {
   4750     if (f != NULL) {
   4751         reader->ctxt->sax->error = xmlTextReaderError;
   4752         reader->ctxt->sax->serror = NULL;
   4753         reader->ctxt->vctxt.error = xmlTextReaderValidityError;
   4754         reader->ctxt->sax->warning = xmlTextReaderWarning;
   4755         reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
   4756         reader->errorFunc = f;
   4757         reader->sErrorFunc = NULL;
   4758         reader->errorFuncArg = arg;
   4759 #ifdef LIBXML_SCHEMAS_ENABLED
   4760         if (reader->rngValidCtxt) {
   4761             xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
   4762                                      xmlTextReaderValidityErrorRelay,
   4763                                      xmlTextReaderValidityWarningRelay,
   4764                                      reader);
   4765             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
   4766                                                reader);
   4767         }
   4768         if (reader->xsdValidCtxt) {
   4769             xmlSchemaSetValidErrors(reader->xsdValidCtxt,
   4770                                     xmlTextReaderValidityErrorRelay,
   4771                                     xmlTextReaderValidityWarningRelay,
   4772                                     reader);
   4773             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
   4774                                               reader);
   4775         }
   4776 #endif
   4777     } else {
   4778         /* restore defaults */
   4779         reader->ctxt->sax->error = xmlParserError;
   4780         reader->ctxt->vctxt.error = xmlParserValidityError;
   4781         reader->ctxt->sax->warning = xmlParserWarning;
   4782         reader->ctxt->vctxt.warning = xmlParserValidityWarning;
   4783         reader->errorFunc = NULL;
   4784         reader->sErrorFunc = NULL;
   4785         reader->errorFuncArg = NULL;
   4786 #ifdef LIBXML_SCHEMAS_ENABLED
   4787         if (reader->rngValidCtxt) {
   4788             xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
   4789                                      reader);
   4790             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
   4791                                                reader);
   4792         }
   4793         if (reader->xsdValidCtxt) {
   4794             xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
   4795                                     reader);
   4796             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
   4797                                               reader);
   4798         }
   4799 #endif
   4800     }
   4801 }
   4802 
   4803 /**
   4804 * xmlTextReaderSetStructuredErrorHandler:
   4805  * @reader:  the xmlTextReaderPtr used
   4806  * @f:	the callback function to call on error and warnings
   4807  * @arg:    a user argument to pass to the callback function
   4808  *
   4809  * Register a callback function that will be called on error and warnings.
   4810  *
   4811  * If @f is NULL, the default error and warning handlers are restored.
   4812  */
   4813 void
   4814 xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
   4815                                        xmlStructuredErrorFunc f, void *arg)
   4816 {
   4817     if (f != NULL) {
   4818         reader->ctxt->sax->error = NULL;
   4819         reader->ctxt->sax->serror = xmlTextReaderStructuredError;
   4820         reader->ctxt->vctxt.error = xmlTextReaderValidityError;
   4821         reader->ctxt->sax->warning = xmlTextReaderWarning;
   4822         reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
   4823         reader->sErrorFunc = f;
   4824         reader->errorFunc = NULL;
   4825         reader->errorFuncArg = arg;
   4826 #ifdef LIBXML_SCHEMAS_ENABLED
   4827         if (reader->rngValidCtxt) {
   4828             xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
   4829                                      reader);
   4830             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
   4831                                         xmlTextReaderValidityStructuredRelay,
   4832                                                reader);
   4833         }
   4834         if (reader->xsdValidCtxt) {
   4835             xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
   4836                                     reader);
   4837             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
   4838                                        xmlTextReaderValidityStructuredRelay,
   4839                                               reader);
   4840         }
   4841 #endif
   4842     } else {
   4843         /* restore defaults */
   4844         reader->ctxt->sax->error = xmlParserError;
   4845         reader->ctxt->sax->serror = NULL;
   4846         reader->ctxt->vctxt.error = xmlParserValidityError;
   4847         reader->ctxt->sax->warning = xmlParserWarning;
   4848         reader->ctxt->vctxt.warning = xmlParserValidityWarning;
   4849         reader->errorFunc = NULL;
   4850         reader->sErrorFunc = NULL;
   4851         reader->errorFuncArg = NULL;
   4852 #ifdef LIBXML_SCHEMAS_ENABLED
   4853         if (reader->rngValidCtxt) {
   4854             xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
   4855                                      reader);
   4856             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
   4857                                                reader);
   4858         }
   4859         if (reader->xsdValidCtxt) {
   4860             xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
   4861                                     reader);
   4862             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
   4863                                               reader);
   4864         }
   4865 #endif
   4866     }
   4867 }
   4868 
   4869 /**
   4870  * xmlTextReaderIsValid:
   4871  * @reader:  the xmlTextReaderPtr used
   4872  *
   4873  * Retrieve the validity status from the parser context
   4874  *
   4875  * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
   4876  */
   4877 int
   4878 xmlTextReaderIsValid(xmlTextReaderPtr reader)
   4879 {
   4880     if (reader == NULL)
   4881         return (-1);
   4882 #ifdef LIBXML_SCHEMAS_ENABLED
   4883     if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
   4884         return (reader->rngValidErrors == 0);
   4885     if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
   4886         return (reader->xsdValidErrors == 0);
   4887 #endif
   4888     if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
   4889         return (reader->ctxt->valid);
   4890     return (0);
   4891 }
   4892 
   4893 /**
   4894  * xmlTextReaderGetErrorHandler:
   4895  * @reader:  the xmlTextReaderPtr used
   4896  * @f:	the callback function or NULL is no callback has been registered
   4897  * @arg:    a user argument
   4898  *
   4899  * Retrieve the error callback function and user argument.
   4900  */
   4901 void
   4902 xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
   4903                              xmlTextReaderErrorFunc * f, void **arg)
   4904 {
   4905     if (f != NULL)
   4906         *f = reader->errorFunc;
   4907     if (arg != NULL)
   4908         *arg = reader->errorFuncArg;
   4909 }
   4910 /************************************************************************
   4911  *									*
   4912  *	New set (2.6.0) of simpler and more flexible APIs		*
   4913  *									*
   4914  ************************************************************************/
   4915 
   4916 /**
   4917  * xmlTextReaderSetup:
   4918  * @reader:  an XML reader
   4919  * @input: xmlParserInputBufferPtr used to feed the reader, will
   4920  *         be destroyed with it.
   4921  * @URL:  the base URL to use for the document
   4922  * @encoding:  the document encoding, or NULL
   4923  * @options:  a combination of xmlParserOption
   4924  *
   4925  * Setup an XML reader with new options
   4926  *
   4927  * Returns 0 in case of success and -1 in case of error.
   4928  */
   4929 int
   4930 xmlTextReaderSetup(xmlTextReaderPtr reader,
   4931                    xmlParserInputBufferPtr input, const char *URL,
   4932                    const char *encoding, int options)
   4933 {
   4934     if (reader == NULL) {
   4935         if (input != NULL)
   4936 	    xmlFreeParserInputBuffer(input);
   4937         return (-1);
   4938     }
   4939 
   4940     /*
   4941      * we force the generation of compact text nodes on the reader
   4942      * since usr applications should never modify the tree
   4943      */
   4944     options |= XML_PARSE_COMPACT;
   4945 
   4946     reader->doc = NULL;
   4947     reader->entNr = 0;
   4948     reader->parserFlags = options;
   4949     reader->validate = XML_TEXTREADER_NOT_VALIDATE;
   4950     if ((input != NULL) && (reader->input != NULL) &&
   4951         (reader->allocs & XML_TEXTREADER_INPUT)) {
   4952 	xmlFreeParserInputBuffer(reader->input);
   4953 	reader->input = NULL;
   4954 	reader->allocs -= XML_TEXTREADER_INPUT;
   4955     }
   4956     if (input != NULL) {
   4957 	reader->input = input;
   4958 	reader->allocs |= XML_TEXTREADER_INPUT;
   4959     }
   4960     if (reader->buffer == NULL)
   4961         reader->buffer = xmlBufferCreateSize(100);
   4962     if (reader->buffer == NULL) {
   4963         xmlGenericError(xmlGenericErrorContext,
   4964                         "xmlTextReaderSetup : malloc failed\n");
   4965         return (-1);
   4966     }
   4967     if (reader->sax == NULL)
   4968 	reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
   4969     if (reader->sax == NULL) {
   4970         xmlGenericError(xmlGenericErrorContext,
   4971                         "xmlTextReaderSetup : malloc failed\n");
   4972         return (-1);
   4973     }
   4974     xmlSAXVersion(reader->sax, 2);
   4975     reader->startElement = reader->sax->startElement;
   4976     reader->sax->startElement = xmlTextReaderStartElement;
   4977     reader->endElement = reader->sax->endElement;
   4978     reader->sax->endElement = xmlTextReaderEndElement;
   4979 #ifdef LIBXML_SAX1_ENABLED
   4980     if (reader->sax->initialized == XML_SAX2_MAGIC) {
   4981 #endif /* LIBXML_SAX1_ENABLED */
   4982         reader->startElementNs = reader->sax->startElementNs;
   4983         reader->sax->startElementNs = xmlTextReaderStartElementNs;
   4984         reader->endElementNs = reader->sax->endElementNs;
   4985         reader->sax->endElementNs = xmlTextReaderEndElementNs;
   4986 #ifdef LIBXML_SAX1_ENABLED
   4987     } else {
   4988         reader->startElementNs = NULL;
   4989         reader->endElementNs = NULL;
   4990     }
   4991 #endif /* LIBXML_SAX1_ENABLED */
   4992     reader->characters = reader->sax->characters;
   4993     reader->sax->characters = xmlTextReaderCharacters;
   4994     reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
   4995     reader->cdataBlock = reader->sax->cdataBlock;
   4996     reader->sax->cdataBlock = xmlTextReaderCDataBlock;
   4997 
   4998     reader->mode = XML_TEXTREADER_MODE_INITIAL;
   4999     reader->node = NULL;
   5000     reader->curnode = NULL;
   5001     if (input != NULL) {
   5002         if (reader->input->buffer->use < 4) {
   5003             xmlParserInputBufferRead(input, 4);
   5004         }
   5005         if (reader->ctxt == NULL) {
   5006             if (reader->input->buffer->use >= 4) {
   5007                 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
   5008 		       (const char *) reader->input->buffer->content, 4, URL);
   5009                 reader->base = 0;
   5010                 reader->cur = 4;
   5011             } else {
   5012                 reader->ctxt =
   5013                     xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
   5014                 reader->base = 0;
   5015                 reader->cur = 0;
   5016             }
   5017         } else {
   5018 	    xmlParserInputPtr inputStream;
   5019 	    xmlParserInputBufferPtr buf;
   5020 	    xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
   5021 
   5022 	    xmlCtxtReset(reader->ctxt);
   5023 	    buf = xmlAllocParserInputBuffer(enc);
   5024 	    if (buf == NULL) return(-1);
   5025 	    inputStream = xmlNewInputStream(reader->ctxt);
   5026 	    if (inputStream == NULL) {
   5027 		xmlFreeParserInputBuffer(buf);
   5028 		return(-1);
   5029 	    }
   5030 
   5031 	    if (URL == NULL)
   5032 		inputStream->filename = NULL;
   5033 	    else
   5034 		inputStream->filename = (char *)
   5035 		    xmlCanonicPath((const xmlChar *) URL);
   5036 	    inputStream->buf = buf;
   5037 	    inputStream->base = inputStream->buf->buffer->content;
   5038 	    inputStream->cur = inputStream->buf->buffer->content;
   5039 	    inputStream->end =
   5040             &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
   5041 
   5042 	    inputPush(reader->ctxt, inputStream);
   5043 	    reader->cur = 0;
   5044 	}
   5045         if (reader->ctxt == NULL) {
   5046             xmlGenericError(xmlGenericErrorContext,
   5047                             "xmlTextReaderSetup : malloc failed\n");
   5048             return (-1);
   5049         }
   5050     }
   5051     if (reader->dict != NULL) {
   5052         if (reader->ctxt->dict != NULL) {
   5053 	    if (reader->dict != reader->ctxt->dict) {
   5054 		xmlDictFree(reader->dict);
   5055 		reader->dict = reader->ctxt->dict;
   5056 	    }
   5057 	} else {
   5058 	    reader->ctxt->dict = reader->dict;
   5059 	}
   5060     } else {
   5061 	if (reader->ctxt->dict == NULL)
   5062 	    reader->ctxt->dict = xmlDictCreate();
   5063         reader->dict = reader->ctxt->dict;
   5064     }
   5065     reader->ctxt->_private = reader;
   5066     reader->ctxt->linenumbers = 1;
   5067     reader->ctxt->dictNames = 1;
   5068     /*
   5069      * use the parser dictionnary to allocate all elements and attributes names
   5070      */
   5071     reader->ctxt->docdict = 1;
   5072     reader->ctxt->parseMode = XML_PARSE_READER;
   5073 
   5074 #ifdef LIBXML_XINCLUDE_ENABLED
   5075     if (reader->xincctxt != NULL) {
   5076 	xmlXIncludeFreeContext(reader->xincctxt);
   5077 	reader->xincctxt = NULL;
   5078     }
   5079     if (options & XML_PARSE_XINCLUDE) {
   5080         reader->xinclude = 1;
   5081 	reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
   5082 	options -= XML_PARSE_XINCLUDE;
   5083     } else
   5084         reader->xinclude = 0;
   5085     reader->in_xinclude = 0;
   5086 #endif
   5087 #ifdef LIBXML_PATTERN_ENABLED
   5088     if (reader->patternTab == NULL) {
   5089         reader->patternNr = 0;
   5090 	reader->patternMax = 0;
   5091     }
   5092     while (reader->patternNr > 0) {
   5093         reader->patternNr--;
   5094 	if (reader->patternTab[reader->patternNr] != NULL) {
   5095 	    xmlFreePattern(reader->patternTab[reader->patternNr]);
   5096             reader->patternTab[reader->patternNr] = NULL;
   5097 	}
   5098     }
   5099 #endif
   5100 
   5101     if (options & XML_PARSE_DTDVALID)
   5102         reader->validate = XML_TEXTREADER_VALIDATE_DTD;
   5103 
   5104     xmlCtxtUseOptions(reader->ctxt, options);
   5105     if (encoding != NULL) {
   5106         xmlCharEncodingHandlerPtr hdlr;
   5107 
   5108         hdlr = xmlFindCharEncodingHandler(encoding);
   5109         if (hdlr != NULL)
   5110             xmlSwitchToEncoding(reader->ctxt, hdlr);
   5111     }
   5112     if ((URL != NULL) && (reader->ctxt->input != NULL) &&
   5113         (reader->ctxt->input->filename == NULL))
   5114         reader->ctxt->input->filename = (char *)
   5115             xmlStrdup((const xmlChar *) URL);
   5116 
   5117     reader->doc = NULL;
   5118 
   5119     return (0);
   5120 }
   5121 
   5122 /**
   5123  * xmlTextReaderByteConsumed:
   5124  * @reader: an XML reader
   5125  *
   5126  * This function provides the current index of the parser used
   5127  * by the reader, relative to the start of the current entity.
   5128  * This function actually just wraps a call to xmlBytesConsumed()
   5129  * for the parser context associated with the reader.
   5130  * See xmlBytesConsumed() for more information.
   5131  *
   5132  * Returns the index in bytes from the beginning of the entity or -1
   5133  *         in case the index could not be computed.
   5134  */
   5135 long
   5136 xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
   5137     if ((reader == NULL) || (reader->ctxt == NULL))
   5138         return(-1);
   5139     return(xmlByteConsumed(reader->ctxt));
   5140 }
   5141 
   5142 
   5143 /**
   5144  * xmlReaderWalker:
   5145  * @doc:  a preparsed document
   5146  *
   5147  * Create an xmltextReader for a preparsed document.
   5148  *
   5149  * Returns the new reader or NULL in case of error.
   5150  */
   5151 xmlTextReaderPtr
   5152 xmlReaderWalker(xmlDocPtr doc)
   5153 {
   5154     xmlTextReaderPtr ret;
   5155 
   5156     if (doc == NULL)
   5157         return(NULL);
   5158 
   5159     ret = xmlMalloc(sizeof(xmlTextReader));
   5160     if (ret == NULL) {
   5161         xmlGenericError(xmlGenericErrorContext,
   5162 		"xmlNewTextReader : malloc failed\n");
   5163 	return(NULL);
   5164     }
   5165     memset(ret, 0, sizeof(xmlTextReader));
   5166     ret->entNr = 0;
   5167     ret->input = NULL;
   5168     ret->mode = XML_TEXTREADER_MODE_INITIAL;
   5169     ret->node = NULL;
   5170     ret->curnode = NULL;
   5171     ret->base = 0;
   5172     ret->cur = 0;
   5173     ret->allocs = XML_TEXTREADER_CTXT;
   5174     ret->doc = doc;
   5175     ret->state = XML_TEXTREADER_START;
   5176     ret->dict = xmlDictCreate();
   5177     return(ret);
   5178 }
   5179 
   5180 /**
   5181  * xmlReaderForDoc:
   5182  * @cur:  a pointer to a zero terminated string
   5183  * @URL:  the base URL to use for the document
   5184  * @encoding:  the document encoding, or NULL
   5185  * @options:  a combination of xmlParserOption
   5186  *
   5187  * Create an xmltextReader for an XML in-memory document.
   5188  * The parsing flags @options are a combination of xmlParserOption.
   5189  *
   5190  * Returns the new reader or NULL in case of error.
   5191  */
   5192 xmlTextReaderPtr
   5193 xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
   5194                 int options)
   5195 {
   5196     int len;
   5197 
   5198     if (cur == NULL)
   5199         return (NULL);
   5200     len = xmlStrlen(cur);
   5201 
   5202     return (xmlReaderForMemory
   5203             ((const char *) cur, len, URL, encoding, options));
   5204 }
   5205 
   5206 /**
   5207  * xmlReaderForFile:
   5208  * @filename:  a file or URL
   5209  * @encoding:  the document encoding, or NULL
   5210  * @options:  a combination of xmlParserOption
   5211  *
   5212  * parse an XML file from the filesystem or the network.
   5213  * The parsing flags @options are a combination of xmlParserOption.
   5214  *
   5215  * Returns the new reader or NULL in case of error.
   5216  */
   5217 xmlTextReaderPtr
   5218 xmlReaderForFile(const char *filename, const char *encoding, int options)
   5219 {
   5220     xmlTextReaderPtr reader;
   5221 
   5222     reader = xmlNewTextReaderFilename(filename);
   5223     if (reader == NULL)
   5224         return (NULL);
   5225     xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
   5226     return (reader);
   5227 }
   5228 
   5229 /**
   5230  * xmlReaderForMemory:
   5231  * @buffer:  a pointer to a char array
   5232  * @size:  the size of the array
   5233  * @URL:  the base URL to use for the document
   5234  * @encoding:  the document encoding, or NULL
   5235  * @options:  a combination of xmlParserOption
   5236  *
   5237  * Create an xmltextReader for an XML in-memory document.
   5238  * The parsing flags @options are a combination of xmlParserOption.
   5239  *
   5240  * Returns the new reader or NULL in case of error.
   5241  */
   5242 xmlTextReaderPtr
   5243 xmlReaderForMemory(const char *buffer, int size, const char *URL,
   5244                    const char *encoding, int options)
   5245 {
   5246     xmlTextReaderPtr reader;
   5247     xmlParserInputBufferPtr buf;
   5248 
   5249     buf = xmlParserInputBufferCreateStatic(buffer, size,
   5250                                       XML_CHAR_ENCODING_NONE);
   5251     if (buf == NULL) {
   5252         return (NULL);
   5253     }
   5254     reader = xmlNewTextReader(buf, URL);
   5255     if (reader == NULL) {
   5256         xmlFreeParserInputBuffer(buf);
   5257         return (NULL);
   5258     }
   5259     reader->allocs |= XML_TEXTREADER_INPUT;
   5260     xmlTextReaderSetup(reader, NULL, URL, encoding, options);
   5261     return (reader);
   5262 }
   5263 
   5264 /**
   5265  * xmlReaderForFd:
   5266  * @fd:  an open file descriptor
   5267  * @URL:  the base URL to use for the document
   5268  * @encoding:  the document encoding, or NULL
   5269  * @options:  a combination of xmlParserOption
   5270  *
   5271  * Create an xmltextReader for an XML from a file descriptor.
   5272  * The parsing flags @options are a combination of xmlParserOption.
   5273  * NOTE that the file descriptor will not be closed when the
   5274  *      reader is closed or reset.
   5275  *
   5276  * Returns the new reader or NULL in case of error.
   5277  */
   5278 xmlTextReaderPtr
   5279 xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
   5280 {
   5281     xmlTextReaderPtr reader;
   5282     xmlParserInputBufferPtr input;
   5283 
   5284     if (fd < 0)
   5285         return (NULL);
   5286 
   5287     input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
   5288     if (input == NULL)
   5289         return (NULL);
   5290     input->closecallback = NULL;
   5291     reader = xmlNewTextReader(input, URL);
   5292     if (reader == NULL) {
   5293         xmlFreeParserInputBuffer(input);
   5294         return (NULL);
   5295     }
   5296     reader->allocs |= XML_TEXTREADER_INPUT;
   5297     xmlTextReaderSetup(reader, NULL, URL, encoding, options);
   5298     return (reader);
   5299 }
   5300 
   5301 /**
   5302  * xmlReaderForIO:
   5303  * @ioread:  an I/O read function
   5304  * @ioclose:  an I/O close function
   5305  * @ioctx:  an I/O handler
   5306  * @URL:  the base URL to use for the document
   5307  * @encoding:  the document encoding, or NULL
   5308  * @options:  a combination of xmlParserOption
   5309  *
   5310  * Create an xmltextReader for an XML document from I/O functions and source.
   5311  * The parsing flags @options are a combination of xmlParserOption.
   5312  *
   5313  * Returns the new reader or NULL in case of error.
   5314  */
   5315 xmlTextReaderPtr
   5316 xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
   5317                void *ioctx, const char *URL, const char *encoding,
   5318                int options)
   5319 {
   5320     xmlTextReaderPtr reader;
   5321     xmlParserInputBufferPtr input;
   5322 
   5323     if (ioread == NULL)
   5324         return (NULL);
   5325 
   5326     input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
   5327                                          XML_CHAR_ENCODING_NONE);
   5328     if (input == NULL)
   5329         return (NULL);
   5330     reader = xmlNewTextReader(input, URL);
   5331     if (reader == NULL) {
   5332         xmlFreeParserInputBuffer(input);
   5333         return (NULL);
   5334     }
   5335     reader->allocs |= XML_TEXTREADER_INPUT;
   5336     xmlTextReaderSetup(reader, NULL, URL, encoding, options);
   5337     return (reader);
   5338 }
   5339 
   5340 /**
   5341  * xmlReaderNewWalker:
   5342  * @reader:  an XML reader
   5343  * @doc:  a preparsed document
   5344  *
   5345  * Setup an xmltextReader to parse a preparsed XML document.
   5346  * This reuses the existing @reader xmlTextReader.
   5347  *
   5348  * Returns 0 in case of success and -1 in case of error
   5349  */
   5350 int
   5351 xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
   5352 {
   5353     if (doc == NULL)
   5354         return (-1);
   5355     if (reader == NULL)
   5356         return (-1);
   5357 
   5358     if (reader->input != NULL) {
   5359         xmlFreeParserInputBuffer(reader->input);
   5360     }
   5361     if (reader->ctxt != NULL) {
   5362 	xmlCtxtReset(reader->ctxt);
   5363     }
   5364 
   5365     reader->entNr = 0;
   5366     reader->input = NULL;
   5367     reader->mode = XML_TEXTREADER_MODE_INITIAL;
   5368     reader->node = NULL;
   5369     reader->curnode = NULL;
   5370     reader->base = 0;
   5371     reader->cur = 0;
   5372     reader->allocs = XML_TEXTREADER_CTXT;
   5373     reader->doc = doc;
   5374     reader->state = XML_TEXTREADER_START;
   5375     if (reader->dict == NULL) {
   5376         if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
   5377 	    reader->dict = reader->ctxt->dict;
   5378 	else
   5379 	    reader->dict = xmlDictCreate();
   5380     }
   5381     return(0);
   5382 }
   5383 
   5384 /**
   5385  * xmlReaderNewDoc:
   5386  * @reader:  an XML reader
   5387  * @cur:  a pointer to a zero terminated string
   5388  * @URL:  the base URL to use for the document
   5389  * @encoding:  the document encoding, or NULL
   5390  * @options:  a combination of xmlParserOption
   5391  *
   5392  * Setup an xmltextReader to parse an XML in-memory document.
   5393  * The parsing flags @options are a combination of xmlParserOption.
   5394  * This reuses the existing @reader xmlTextReader.
   5395  *
   5396  * Returns 0 in case of success and -1 in case of error
   5397  */
   5398 int
   5399 xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
   5400                 const char *URL, const char *encoding, int options)
   5401 {
   5402 
   5403     int len;
   5404 
   5405     if (cur == NULL)
   5406         return (-1);
   5407     if (reader == NULL)
   5408         return (-1);
   5409 
   5410     len = xmlStrlen(cur);
   5411     return (xmlReaderNewMemory(reader, (const char *)cur, len,
   5412                                URL, encoding, options));
   5413 }
   5414 
   5415 /**
   5416  * xmlReaderNewFile:
   5417  * @reader:  an XML reader
   5418  * @filename:  a file or URL
   5419  * @encoding:  the document encoding, or NULL
   5420  * @options:  a combination of xmlParserOption
   5421  *
   5422  * parse an XML file from the filesystem or the network.
   5423  * The parsing flags @options are a combination of xmlParserOption.
   5424  * This reuses the existing @reader xmlTextReader.
   5425  *
   5426  * Returns 0 in case of success and -1 in case of error
   5427  */
   5428 int
   5429 xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
   5430                  const char *encoding, int options)
   5431 {
   5432     xmlParserInputBufferPtr input;
   5433 
   5434     if (filename == NULL)
   5435         return (-1);
   5436     if (reader == NULL)
   5437         return (-1);
   5438 
   5439     input =
   5440         xmlParserInputBufferCreateFilename(filename,
   5441                                            XML_CHAR_ENCODING_NONE);
   5442     if (input == NULL)
   5443         return (-1);
   5444     return (xmlTextReaderSetup(reader, input, filename, encoding, options));
   5445 }
   5446 
   5447 /**
   5448  * xmlReaderNewMemory:
   5449  * @reader:  an XML reader
   5450  * @buffer:  a pointer to a char array
   5451  * @size:  the size of the array
   5452  * @URL:  the base URL to use for the document
   5453  * @encoding:  the document encoding, or NULL
   5454  * @options:  a combination of xmlParserOption
   5455  *
   5456  * Setup an xmltextReader to parse an XML in-memory document.
   5457  * The parsing flags @options are a combination of xmlParserOption.
   5458  * This reuses the existing @reader xmlTextReader.
   5459  *
   5460  * Returns 0 in case of success and -1 in case of error
   5461  */
   5462 int
   5463 xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
   5464                    const char *URL, const char *encoding, int options)
   5465 {
   5466     xmlParserInputBufferPtr input;
   5467 
   5468     if (reader == NULL)
   5469         return (-1);
   5470     if (buffer == NULL)
   5471         return (-1);
   5472 
   5473     input = xmlParserInputBufferCreateStatic(buffer, size,
   5474                                       XML_CHAR_ENCODING_NONE);
   5475     if (input == NULL) {
   5476         return (-1);
   5477     }
   5478     return (xmlTextReaderSetup(reader, input, URL, encoding, options));
   5479 }
   5480 
   5481 /**
   5482  * xmlReaderNewFd:
   5483  * @reader:  an XML reader
   5484  * @fd:  an open file descriptor
   5485  * @URL:  the base URL to use for the document
   5486  * @encoding:  the document encoding, or NULL
   5487  * @options:  a combination of xmlParserOption
   5488  *
   5489  * Setup an xmltextReader to parse an XML from a file descriptor.
   5490  * NOTE that the file descriptor will not be closed when the
   5491  *      reader is closed or reset.
   5492  * The parsing flags @options are a combination of xmlParserOption.
   5493  * This reuses the existing @reader xmlTextReader.
   5494  *
   5495  * Returns 0 in case of success and -1 in case of error
   5496  */
   5497 int
   5498 xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
   5499                const char *URL, const char *encoding, int options)
   5500 {
   5501     xmlParserInputBufferPtr input;
   5502 
   5503     if (fd < 0)
   5504         return (-1);
   5505     if (reader == NULL)
   5506         return (-1);
   5507 
   5508     input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
   5509     if (input == NULL)
   5510         return (-1);
   5511     input->closecallback = NULL;
   5512     return (xmlTextReaderSetup(reader, input, URL, encoding, options));
   5513 }
   5514 
   5515 /**
   5516  * xmlReaderNewIO:
   5517  * @reader:  an XML reader
   5518  * @ioread:  an I/O read function
   5519  * @ioclose:  an I/O close function
   5520  * @ioctx:  an I/O handler
   5521  * @URL:  the base URL to use for the document
   5522  * @encoding:  the document encoding, or NULL
   5523  * @options:  a combination of xmlParserOption
   5524  *
   5525  * Setup an xmltextReader to parse an XML document from I/O functions
   5526  * and source.
   5527  * The parsing flags @options are a combination of xmlParserOption.
   5528  * This reuses the existing @reader xmlTextReader.
   5529  *
   5530  * Returns 0 in case of success and -1 in case of error
   5531  */
   5532 int
   5533 xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
   5534                xmlInputCloseCallback ioclose, void *ioctx,
   5535                const char *URL, const char *encoding, int options)
   5536 {
   5537     xmlParserInputBufferPtr input;
   5538 
   5539     if (ioread == NULL)
   5540         return (-1);
   5541     if (reader == NULL)
   5542         return (-1);
   5543 
   5544     input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
   5545                                          XML_CHAR_ENCODING_NONE);
   5546     if (input == NULL)
   5547         return (-1);
   5548     return (xmlTextReaderSetup(reader, input, URL, encoding, options));
   5549 }
   5550 /************************************************************************
   5551  *									*
   5552  *			Utilities					*
   5553  *									*
   5554  ************************************************************************/
   5555 #ifdef NOT_USED_YET
   5556 
   5557 /**
   5558  * xmlBase64Decode:
   5559  * @in:  the input buffer
   5560  * @inlen:  the size of the input (in), the size read from it (out)
   5561  * @to:  the output buffer
   5562  * @tolen:  the size of the output (in), the size written to (out)
   5563  *
   5564  * Base64 decoder, reads from @in and save in @to
   5565  * TODO: tell jody when this is actually exported
   5566  *
   5567  * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
   5568  *         2 if there wasn't enough space on the output or -1 in case of error.
   5569  */
   5570 static int
   5571 xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
   5572                 unsigned char *to, unsigned long *tolen)
   5573 {
   5574     unsigned long incur;        /* current index in in[] */
   5575 
   5576     unsigned long inblk;        /* last block index in in[] */
   5577 
   5578     unsigned long outcur;       /* current index in out[] */
   5579 
   5580     unsigned long inmax;        /* size of in[] */
   5581 
   5582     unsigned long outmax;       /* size of out[] */
   5583 
   5584     unsigned char cur;          /* the current value read from in[] */
   5585 
   5586     unsigned char intmp[4], outtmp[4];  /* temporary buffers for the convert */
   5587 
   5588     int nbintmp;                /* number of byte in intmp[] */
   5589 
   5590     int is_ignore;              /* cur should be ignored */
   5591 
   5592     int is_end = 0;             /* the end of the base64 was found */
   5593 
   5594     int retval = 1;
   5595 
   5596     int i;
   5597 
   5598     if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
   5599         return (-1);
   5600 
   5601     incur = 0;
   5602     inblk = 0;
   5603     outcur = 0;
   5604     inmax = *inlen;
   5605     outmax = *tolen;
   5606     nbintmp = 0;
   5607 
   5608     while (1) {
   5609         if (incur >= inmax)
   5610             break;
   5611         cur = in[incur++];
   5612         is_ignore = 0;
   5613         if ((cur >= 'A') && (cur <= 'Z'))
   5614             cur = cur - 'A';
   5615         else if ((cur >= 'a') && (cur <= 'z'))
   5616             cur = cur - 'a' + 26;
   5617         else if ((cur >= '0') && (cur <= '9'))
   5618             cur = cur - '0' + 52;
   5619         else if (cur == '+')
   5620             cur = 62;
   5621         else if (cur == '/')
   5622             cur = 63;
   5623         else if (cur == '.')
   5624             cur = 0;
   5625         else if (cur == '=')    /*no op , end of the base64 stream */
   5626             is_end = 1;
   5627         else {
   5628             is_ignore = 1;
   5629             if (nbintmp == 0)
   5630                 inblk = incur;
   5631         }
   5632 
   5633         if (!is_ignore) {
   5634             int nbouttmp = 3;
   5635 
   5636             int is_break = 0;
   5637 
   5638             if (is_end) {
   5639                 if (nbintmp == 0)
   5640                     break;
   5641                 if ((nbintmp == 1) || (nbintmp == 2))
   5642                     nbouttmp = 1;
   5643                 else
   5644                     nbouttmp = 2;
   5645                 nbintmp = 3;
   5646                 is_break = 1;
   5647             }
   5648             intmp[nbintmp++] = cur;
   5649             /*
   5650              * if intmp is full, push the 4byte sequence as a 3 byte
   5651              * sequence out
   5652              */
   5653             if (nbintmp == 4) {
   5654                 nbintmp = 0;
   5655                 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
   5656                 outtmp[1] =
   5657                     ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
   5658                 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
   5659                 if (outcur + 3 >= outmax) {
   5660                     retval = 2;
   5661                     break;
   5662                 }
   5663 
   5664                 for (i = 0; i < nbouttmp; i++)
   5665                     to[outcur++] = outtmp[i];
   5666                 inblk = incur;
   5667             }
   5668 
   5669             if (is_break) {
   5670                 retval = 0;
   5671                 break;
   5672             }
   5673         }
   5674     }
   5675 
   5676     *tolen = outcur;
   5677     *inlen = inblk;
   5678     return (retval);
   5679 }
   5680 
   5681 /*
   5682  * Test routine for the xmlBase64Decode function
   5683  */
   5684 #if 0
   5685 int
   5686 main(int argc, char **argv)
   5687 {
   5688     char *input = "  VW4 gcGV0        \n      aXQgdGVzdCAuCg== ";
   5689 
   5690     char output[100];
   5691 
   5692     char output2[100];
   5693 
   5694     char output3[100];
   5695 
   5696     unsigned long inlen = strlen(input);
   5697 
   5698     unsigned long outlen = 100;
   5699 
   5700     int ret;
   5701 
   5702     unsigned long cons, tmp, tmp2, prod;
   5703 
   5704     /*
   5705      * Direct
   5706      */
   5707     ret = xmlBase64Decode(input, &inlen, output, &outlen);
   5708 
   5709     output[outlen] = 0;
   5710     printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen,
   5711            outlen, output)indent: Standard input:179: Error:Unmatched #endif
   5712 ;
   5713 
   5714     /*
   5715      * output chunking
   5716      */
   5717     cons = 0;
   5718     prod = 0;
   5719     while (cons < inlen) {
   5720         tmp = 5;
   5721         tmp2 = inlen - cons;
   5722 
   5723         printf("%ld %ld\n", cons, prod);
   5724         ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
   5725         cons += tmp2;
   5726         prod += tmp;
   5727         printf("%ld %ld\n", cons, prod);
   5728     }
   5729     output2[outlen] = 0;
   5730     printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
   5731            prod, output2);
   5732 
   5733     /*
   5734      * input chunking
   5735      */
   5736     cons = 0;
   5737     prod = 0;
   5738     while (cons < inlen) {
   5739         tmp = 100 - prod;
   5740         tmp2 = inlen - cons;
   5741         if (tmp2 > 5)
   5742             tmp2 = 5;
   5743 
   5744         printf("%ld %ld\n", cons, prod);
   5745         ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
   5746         cons += tmp2;
   5747         prod += tmp;
   5748         printf("%ld %ld\n", cons, prod);
   5749     }
   5750     output3[outlen] = 0;
   5751     printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
   5752            prod, output3);
   5753     return (0);
   5754 
   5755 }
   5756 #endif
   5757 #endif /* NOT_USED_YET */
   5758 #define bottom_xmlreader
   5759 #include "elfgcchack.h"
   5760 #endif /* LIBXML_READER_ENABLED */
   5761