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