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