mirror of
				https://gitlab.gnome.org/GNOME/libxml2.git
				synced 2025-10-24 13:33:01 +03:00 
			
		
		
		
	Remove checks now that we can shrink memory buffers efficiently. Shrink more aggressively.
		
			
				
	
	
		
			5477 lines
		
	
	
		
			152 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			5477 lines
		
	
	
		
			152 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * xmlreader.c: implements the xmlTextReader streaming node API
 | |
|  *
 | |
|  * NOTE:
 | |
|  *   XmlTextReader.Normalization Property won't be supported, since
 | |
|  *     it makes the parser non compliant to the XML recommendation
 | |
|  *
 | |
|  * See Copyright for the status of this software.
 | |
|  *
 | |
|  * daniel@veillard.com
 | |
|  */
 | |
| 
 | |
| /*
 | |
|  * TODOs:
 | |
|  *   - XML Schemas validation
 | |
|  */
 | |
| #define IN_LIBXML
 | |
| #include "libxml.h"
 | |
| 
 | |
| #ifdef LIBXML_READER_ENABLED
 | |
| #include <string.h> /* for memset() only ! */
 | |
| #include <stdarg.h>
 | |
| #include <ctype.h>
 | |
| #include <stdlib.h>
 | |
| 
 | |
| #include <libxml/xmlmemory.h>
 | |
| #include <libxml/xmlIO.h>
 | |
| #include <libxml/xmlreader.h>
 | |
| #include <libxml/parserInternals.h>
 | |
| #ifdef LIBXML_SCHEMAS_ENABLED
 | |
| #include <libxml/relaxng.h>
 | |
| #include <libxml/xmlschemas.h>
 | |
| #endif
 | |
| #include <libxml/uri.h>
 | |
| #ifdef LIBXML_XINCLUDE_ENABLED
 | |
| #include <libxml/xinclude.h>
 | |
| #endif
 | |
| #ifdef LIBXML_PATTERN_ENABLED
 | |
| #include <libxml/pattern.h>
 | |
| #endif
 | |
| 
 | |
| #include "private/buf.h"
 | |
| #include "private/error.h"
 | |
| #include "private/tree.h"
 | |
| #include "private/parser.h"
 | |
| #ifdef LIBXML_XINCLUDE_ENABLED
 | |
| #include "private/xinclude.h"
 | |
| #endif
 | |
| 
 | |
| #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
 | |
| /* Keeping free objects can hide memory errors. */
 | |
| #define MAX_FREE_NODES 1
 | |
| #else
 | |
| #define MAX_FREE_NODES 100
 | |
| #endif
 | |
| 
 | |
| #ifndef va_copy
 | |
|   #ifdef __va_copy
 | |
|     #define va_copy(dest, src) __va_copy(dest, src)
 | |
|   #else
 | |
|     #define va_copy(dest, src) memcpy(dest, src, sizeof(va_list))
 | |
|   #endif
 | |
| #endif
 | |
| 
 | |
| #define CHUNK_SIZE 512
 | |
| /************************************************************************
 | |
|  *									*
 | |
|  *	The parser: maps the Text Reader API on top of the existing	*
 | |
|  *		parsing routines building a tree			*
 | |
|  *									*
 | |
|  ************************************************************************/
 | |
| 
 | |
| #define XML_TEXTREADER_INPUT	1
 | |
| #define XML_TEXTREADER_CTXT	2
 | |
| 
 | |
| typedef enum {
 | |
|     XML_TEXTREADER_NONE = -1,
 | |
|     XML_TEXTREADER_START= 0,
 | |
|     XML_TEXTREADER_ELEMENT= 1,
 | |
|     XML_TEXTREADER_END= 2,
 | |
|     XML_TEXTREADER_EMPTY= 3,
 | |
|     XML_TEXTREADER_BACKTRACK= 4,
 | |
|     XML_TEXTREADER_DONE= 5,
 | |
|     XML_TEXTREADER_ERROR= 6
 | |
| } xmlTextReaderState;
 | |
| 
 | |
| typedef enum {
 | |
|     XML_TEXTREADER_NOT_VALIDATE = 0,
 | |
|     XML_TEXTREADER_VALIDATE_DTD = 1,
 | |
|     XML_TEXTREADER_VALIDATE_RNG = 2,
 | |
|     XML_TEXTREADER_VALIDATE_XSD = 4
 | |
| } xmlTextReaderValidate;
 | |
| 
 | |
| struct _xmlTextReader {
 | |
|     int				mode;	/* the parsing mode */
 | |
|     xmlDocPtr			doc;    /* when walking an existing doc */
 | |
|     xmlTextReaderValidate       validate;/* is there any validation */
 | |
|     int				allocs;	/* what structure were deallocated */
 | |
|     xmlTextReaderState		state;
 | |
|     xmlParserCtxtPtr		ctxt;	/* the parser context */
 | |
|     xmlSAXHandlerPtr		sax;	/* the parser SAX callbacks */
 | |
|     xmlParserInputBufferPtr	input;	/* the input */
 | |
|     startElementSAXFunc		startElement;/* initial SAX callbacks */
 | |
|     endElementSAXFunc		endElement;  /* idem */
 | |
|     startElementNsSAX2Func	startElementNs;/* idem */
 | |
|     endElementNsSAX2Func	endElementNs;  /* idem */
 | |
|     charactersSAXFunc		characters;
 | |
|     cdataBlockSAXFunc		cdataBlock;
 | |
|     unsigned int		base;	/* base of the segment in the input */
 | |
|     unsigned int		cur;	/* current position in the input */
 | |
|     xmlNodePtr			node;	/* current node */
 | |
|     xmlNodePtr			curnode;/* current attribute node */
 | |
|     int				depth;  /* depth of the current node */
 | |
|     xmlNodePtr			faketext;/* fake xmlNs chld */
 | |
|     int				preserve;/* preserve the resulting document */
 | |
|     xmlBufPtr		        buffer; /* used to return const xmlChar * */
 | |
|     xmlDictPtr			dict;	/* the context dictionary */
 | |
| 
 | |
|     /* entity stack when traversing entities content */
 | |
|     xmlNodePtr         ent;          /* Current Entity Ref Node */
 | |
|     int                entNr;        /* Depth of the entities stack */
 | |
|     int                entMax;       /* Max depth of the entities stack */
 | |
|     xmlNodePtr        *entTab;       /* array of entities */
 | |
| 
 | |
|     /* error handling */
 | |
|     xmlTextReaderErrorFunc errorFunc;    /* callback function */
 | |
|     void                  *errorFuncArg; /* callback function user argument */
 | |
| 
 | |
| #ifdef LIBXML_SCHEMAS_ENABLED
 | |
|     /* Handling of RelaxNG validation */
 | |
|     xmlRelaxNGPtr          rngSchemas;	/* The Relax NG schemas */
 | |
|     xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */
 | |
|     int                    rngPreserveCtxt; /* 1 if the context was provided by the user */
 | |
|     int                    rngValidErrors;/* The number of errors detected */
 | |
|     xmlNodePtr             rngFullNode;	/* the node if RNG not progressive */
 | |
|     /* Handling of Schemas validation */
 | |
|     xmlSchemaPtr          xsdSchemas;	/* The Schemas schemas */
 | |
|     xmlSchemaValidCtxtPtr xsdValidCtxt;/* The Schemas validation context */
 | |
|     int                   xsdPreserveCtxt; /* 1 if the context was provided by the user */
 | |
|     int                   xsdValidErrors;/* The number of errors detected */
 | |
|     xmlSchemaSAXPlugPtr   xsdPlug;	/* the schemas plug in SAX pipeline */
 | |
| #endif
 | |
| #ifdef LIBXML_XINCLUDE_ENABLED
 | |
|     /* Handling of XInclude processing */
 | |
|     int                xinclude;	/* is xinclude asked for */
 | |
|     const xmlChar *    xinclude_name;	/* the xinclude name from dict */
 | |
|     xmlXIncludeCtxtPtr xincctxt;	/* the xinclude context */
 | |
|     int                in_xinclude;	/* counts for xinclude */
 | |
| #endif
 | |
| #ifdef LIBXML_PATTERN_ENABLED
 | |
|     int                patternNr;       /* number of preserve patterns */
 | |
|     int                patternMax;      /* max preserve patterns */
 | |
|     xmlPatternPtr     *patternTab;      /* array of preserve patterns */
 | |
| #endif
 | |
|     int                preserves;	/* level of preserves */
 | |
|     int                parserFlags;	/* the set of options set */
 | |
|     /* Structured error handling */
 | |
|     xmlStructuredErrorFunc sErrorFunc;  /* callback function */
 | |
| 
 | |
|     xmlResourceLoader resourceLoader;
 | |
|     void *resourceCtxt;
 | |
| };
 | |
| 
 | |
| #define NODE_IS_EMPTY		0x1
 | |
| #define NODE_IS_PRESERVED	0x2
 | |
| #define NODE_IS_SPRESERVED	0x4
 | |
| 
 | |
| static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
 | |
| static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
 | |
| 
 | |
| /**
 | |
|  * DICT_FREE:
 | |
|  * @str:  a string
 | |
|  *
 | |
|  * Free a string if it is not owned by the "dict" dictionary in the
 | |
|  * current scope
 | |
|  */
 | |
| #define DICT_FREE(str)						\
 | |
| 	if ((str) && ((!dict) ||				\
 | |
| 	    (xmlDictOwns(dict, (const xmlChar *)(str)) == 0)))	\
 | |
| 	    xmlFree((char *)(str));
 | |
| 
 | |
| static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
 | |
| static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
 | |
| 
 | |
| static void
 | |
| xmlTextReaderErrMemory(xmlTextReaderPtr reader) {
 | |
|     if (reader->ctxt != NULL)
 | |
|         xmlCtxtErrMemory(reader->ctxt);
 | |
|     else
 | |
|         xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_PARSER, NULL);
 | |
|     reader->mode = XML_TEXTREADER_MODE_ERROR;
 | |
|     reader->state = XML_TEXTREADER_ERROR;
 | |
| }
 | |
| 
 | |
| static xmlChar *
 | |
| readerStrdup(xmlTextReaderPtr reader, const xmlChar *string) {
 | |
|     xmlChar *copy;
 | |
| 
 | |
|     if (string == NULL)
 | |
|         return(NULL);
 | |
| 
 | |
|     copy = xmlStrdup(string);
 | |
|     if (copy == NULL)
 | |
|         xmlTextReaderErrMemory(reader);
 | |
| 
 | |
|     return(copy);
 | |
| }
 | |
| 
 | |
| static const xmlChar *
 | |
| constString(xmlTextReaderPtr reader, const xmlChar *string) {
 | |
|     const xmlChar *dictString;
 | |
| 
 | |
|     if (string == NULL)
 | |
|         return(NULL);
 | |
| 
 | |
|     dictString = xmlDictLookup(reader->dict, string, -1);
 | |
|     if (dictString == NULL)
 | |
|         xmlTextReaderErrMemory(reader);
 | |
| 
 | |
|     return(dictString);
 | |
| }
 | |
| 
 | |
| static const xmlChar *
 | |
| constQString(xmlTextReaderPtr reader, const xmlChar *prefix,
 | |
|              const xmlChar *name) {
 | |
|     const xmlChar *dictString;
 | |
| 
 | |
|     if (name == NULL)
 | |
|         return(NULL);
 | |
| 
 | |
|     dictString = xmlDictQLookup(reader->dict, prefix, name);
 | |
|     if (dictString == NULL)
 | |
|         xmlTextReaderErrMemory(reader);
 | |
| 
 | |
|     return(dictString);
 | |
| }
 | |
| 
 | |
| /************************************************************************
 | |
|  *									*
 | |
|  *	Our own version of the freeing routines as we recycle nodes	*
 | |
|  *									*
 | |
|  ************************************************************************/
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderFreeProp:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @cur:  the node
 | |
|  *
 | |
|  * Free a node.
 | |
|  */
 | |
| static void
 | |
| xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
 | |
|     xmlDictPtr dict;
 | |
| 
 | |
|     if ((reader != NULL) && (reader->ctxt != NULL))
 | |
| 	dict = reader->ctxt->dict;
 | |
|     else
 | |
|         dict = NULL;
 | |
|     if (cur == NULL) return;
 | |
| 
 | |
|     if ((xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
 | |
| 	xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
 | |
| 
 | |
|     if (cur->children != NULL)
 | |
|         xmlTextReaderFreeNodeList(reader, cur->children);
 | |
| 
 | |
|     if (cur->id != NULL) {
 | |
|         /*
 | |
|          * Operating in streaming mode, attr is gonna disappear
 | |
|          */
 | |
|         cur->id->attr = NULL;
 | |
|         if (cur->id->name != NULL)
 | |
|             DICT_FREE(cur->id->name);
 | |
|         cur->id->name = cur->name;
 | |
|         cur->name = NULL;
 | |
|     } else {
 | |
|         DICT_FREE(cur->name);
 | |
|     }
 | |
| 
 | |
|     if ((reader != NULL) && (reader->ctxt != NULL) &&
 | |
|         (reader->ctxt->freeAttrsNr < MAX_FREE_NODES)) {
 | |
|         cur->next = reader->ctxt->freeAttrs;
 | |
| 	reader->ctxt->freeAttrs = cur;
 | |
| 	reader->ctxt->freeAttrsNr++;
 | |
|     } else {
 | |
| 	xmlFree(cur);
 | |
|     }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderFreePropList:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @cur:  the first property in the list
 | |
|  *
 | |
|  * Free a property and all its siblings, all the children are freed too.
 | |
|  */
 | |
| static void
 | |
| xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
 | |
|     xmlAttrPtr next;
 | |
| 
 | |
|     while (cur != NULL) {
 | |
|         next = cur->next;
 | |
|         xmlTextReaderFreeProp(reader, cur);
 | |
| 	cur = next;
 | |
|     }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderFreeNodeList:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @cur:  the first node in the list
 | |
|  *
 | |
|  * Free a node and all its siblings, this is a recursive behaviour, all
 | |
|  * the children are freed too.
 | |
|  */
 | |
| static void
 | |
| xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
 | |
|     xmlNodePtr next;
 | |
|     xmlNodePtr parent;
 | |
|     xmlDictPtr dict;
 | |
|     size_t depth = 0;
 | |
| 
 | |
|     if ((reader != NULL) && (reader->ctxt != NULL))
 | |
| 	dict = reader->ctxt->dict;
 | |
|     else
 | |
|         dict = NULL;
 | |
|     if (cur == NULL) return;
 | |
|     if (cur->type == XML_NAMESPACE_DECL) {
 | |
| 	xmlFreeNsList((xmlNsPtr) cur);
 | |
| 	return;
 | |
|     }
 | |
|     if ((cur->type == XML_DOCUMENT_NODE) ||
 | |
| 	(cur->type == XML_HTML_DOCUMENT_NODE)) {
 | |
| 	xmlFreeDoc((xmlDocPtr) cur);
 | |
| 	return;
 | |
|     }
 | |
|     while (1) {
 | |
|         while ((cur->type != XML_DTD_NODE) &&
 | |
|                (cur->type != XML_ENTITY_REF_NODE) &&
 | |
|                (cur->children != NULL) &&
 | |
|                (cur->children->parent == cur)) {
 | |
|             cur = cur->children;
 | |
|             depth += 1;
 | |
|         }
 | |
| 
 | |
|         next = cur->next;
 | |
|         parent = cur->parent;
 | |
| 
 | |
| 	/* unroll to speed up freeing the document */
 | |
| 	if (cur->type != XML_DTD_NODE) {
 | |
| 
 | |
| 	    if ((xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
 | |
| 		xmlDeregisterNodeDefaultValue(cur);
 | |
| 
 | |
| 	    if (((cur->type == XML_ELEMENT_NODE) ||
 | |
| 		 (cur->type == XML_XINCLUDE_START) ||
 | |
| 		 (cur->type == XML_XINCLUDE_END)) &&
 | |
| 		(cur->properties != NULL))
 | |
| 		xmlTextReaderFreePropList(reader, cur->properties);
 | |
| 	    if ((cur->content != (xmlChar *) &(cur->properties)) &&
 | |
| 	        (cur->type != XML_ELEMENT_NODE) &&
 | |
| 		(cur->type != XML_XINCLUDE_START) &&
 | |
| 		(cur->type != XML_XINCLUDE_END) &&
 | |
| 		(cur->type != XML_ENTITY_REF_NODE)) {
 | |
| 		DICT_FREE(cur->content);
 | |
| 	    }
 | |
| 	    if (((cur->type == XML_ELEMENT_NODE) ||
 | |
| 	         (cur->type == XML_XINCLUDE_START) ||
 | |
| 		 (cur->type == XML_XINCLUDE_END)) &&
 | |
| 		(cur->nsDef != NULL))
 | |
| 		xmlFreeNsList(cur->nsDef);
 | |
| 
 | |
| 	    /*
 | |
| 	     * we don't free element names here they are interned now
 | |
| 	     */
 | |
| 	    if ((cur->type != XML_TEXT_NODE) &&
 | |
| 		(cur->type != XML_COMMENT_NODE))
 | |
| 		DICT_FREE(cur->name);
 | |
| 	    if (((cur->type == XML_ELEMENT_NODE) ||
 | |
| 		 (cur->type == XML_TEXT_NODE)) &&
 | |
| 	        (reader != NULL) && (reader->ctxt != NULL) &&
 | |
| 		(reader->ctxt->freeElemsNr < MAX_FREE_NODES)) {
 | |
| 	        cur->next = reader->ctxt->freeElems;
 | |
| 		reader->ctxt->freeElems = cur;
 | |
| 		reader->ctxt->freeElemsNr++;
 | |
| 	    } else {
 | |
| 		xmlFree(cur);
 | |
| 	    }
 | |
| 	}
 | |
| 
 | |
|         if (next != NULL) {
 | |
| 	    cur = next;
 | |
|         } else {
 | |
|             if ((depth == 0) || (parent == NULL))
 | |
|                 break;
 | |
|             depth -= 1;
 | |
|             cur = parent;
 | |
|             cur->children = NULL;
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderFreeNode:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @cur:  the node
 | |
|  *
 | |
|  * Free a node, this is a recursive behaviour, all the children are freed too.
 | |
|  * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
 | |
|  */
 | |
| static void
 | |
| xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
 | |
|     xmlDictPtr dict;
 | |
| 
 | |
|     if ((reader != NULL) && (reader->ctxt != NULL))
 | |
| 	dict = reader->ctxt->dict;
 | |
|     else
 | |
|         dict = NULL;
 | |
|     if (cur->type == XML_DTD_NODE) {
 | |
| 	xmlFreeDtd((xmlDtdPtr) cur);
 | |
| 	return;
 | |
|     }
 | |
|     if (cur->type == XML_NAMESPACE_DECL) {
 | |
| 	xmlFreeNs((xmlNsPtr) cur);
 | |
|         return;
 | |
|     }
 | |
|     if (cur->type == XML_ATTRIBUTE_NODE) {
 | |
| 	xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
 | |
| 	return;
 | |
|     }
 | |
| 
 | |
|     if ((cur->children != NULL) &&
 | |
| 	(cur->type != XML_ENTITY_REF_NODE)) {
 | |
| 	if (cur->children->parent == cur)
 | |
| 	    xmlTextReaderFreeNodeList(reader, cur->children);
 | |
| 	cur->children = NULL;
 | |
|     }
 | |
| 
 | |
|     if ((xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
 | |
| 	xmlDeregisterNodeDefaultValue(cur);
 | |
| 
 | |
|     if (((cur->type == XML_ELEMENT_NODE) ||
 | |
| 	 (cur->type == XML_XINCLUDE_START) ||
 | |
| 	 (cur->type == XML_XINCLUDE_END)) &&
 | |
| 	(cur->properties != NULL))
 | |
| 	xmlTextReaderFreePropList(reader, cur->properties);
 | |
|     if ((cur->content != (xmlChar *) &(cur->properties)) &&
 | |
|         (cur->type != XML_ELEMENT_NODE) &&
 | |
| 	(cur->type != XML_XINCLUDE_START) &&
 | |
| 	(cur->type != XML_XINCLUDE_END) &&
 | |
| 	(cur->type != XML_ENTITY_REF_NODE)) {
 | |
| 	DICT_FREE(cur->content);
 | |
|     }
 | |
|     if (((cur->type == XML_ELEMENT_NODE) ||
 | |
| 	 (cur->type == XML_XINCLUDE_START) ||
 | |
| 	 (cur->type == XML_XINCLUDE_END)) &&
 | |
| 	(cur->nsDef != NULL))
 | |
| 	xmlFreeNsList(cur->nsDef);
 | |
| 
 | |
|     /*
 | |
|      * we don't free names here they are interned now
 | |
|      */
 | |
|     if ((cur->type != XML_TEXT_NODE) &&
 | |
|         (cur->type != XML_COMMENT_NODE))
 | |
| 	DICT_FREE(cur->name);
 | |
| 
 | |
|     if (((cur->type == XML_ELEMENT_NODE) ||
 | |
| 	 (cur->type == XML_TEXT_NODE)) &&
 | |
| 	(reader != NULL) && (reader->ctxt != NULL) &&
 | |
| 	(reader->ctxt->freeElemsNr < MAX_FREE_NODES)) {
 | |
| 	cur->next = reader->ctxt->freeElems;
 | |
| 	reader->ctxt->freeElems = cur;
 | |
| 	reader->ctxt->freeElemsNr++;
 | |
|     } else {
 | |
| 	xmlFree(cur);
 | |
|     }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderFreeDoc:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @cur:  pointer to the document
 | |
|  *
 | |
|  * Free up all the structures used by a document, tree included.
 | |
|  */
 | |
| static void
 | |
| xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
 | |
|     xmlDtdPtr extSubset, intSubset;
 | |
| 
 | |
|     if (cur == NULL) return;
 | |
| 
 | |
|     if ((xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
 | |
| 	xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
 | |
| 
 | |
|     /*
 | |
|      * Do this before freeing the children list to avoid ID lookups
 | |
|      */
 | |
|     if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
 | |
|     cur->ids = NULL;
 | |
|     if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
 | |
|     cur->refs = NULL;
 | |
|     extSubset = cur->extSubset;
 | |
|     intSubset = cur->intSubset;
 | |
|     if (intSubset == extSubset)
 | |
| 	extSubset = NULL;
 | |
|     if (extSubset != NULL) {
 | |
| 	xmlUnlinkNode((xmlNodePtr) cur->extSubset);
 | |
| 	cur->extSubset = NULL;
 | |
| 	xmlFreeDtd(extSubset);
 | |
|     }
 | |
|     if (intSubset != NULL) {
 | |
| 	xmlUnlinkNode((xmlNodePtr) cur->intSubset);
 | |
| 	cur->intSubset = NULL;
 | |
| 	xmlFreeDtd(intSubset);
 | |
|     }
 | |
| 
 | |
|     if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
 | |
| 
 | |
|     if (cur->version != NULL) xmlFree((char *) cur->version);
 | |
|     if (cur->name != NULL) xmlFree((char *) cur->name);
 | |
|     if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
 | |
|     if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
 | |
|     if (cur->URL != NULL) xmlFree((char *) cur->URL);
 | |
|     if (cur->dict != NULL) xmlDictFree(cur->dict);
 | |
| 
 | |
|     xmlFree(cur);
 | |
| }
 | |
| 
 | |
| /************************************************************************
 | |
|  *									*
 | |
|  *			The reader core parser				*
 | |
|  *									*
 | |
|  ************************************************************************/
 | |
| 
 | |
| static void
 | |
| xmlTextReaderStructuredRelay(void *userData, const xmlError *error)
 | |
| {
 | |
|     xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
 | |
| 
 | |
|     if (reader->sErrorFunc != NULL) {
 | |
|         reader->sErrorFunc(reader->errorFuncArg, error);
 | |
|     } else if (reader->errorFunc != NULL) {
 | |
|         xmlParserSeverities severity;
 | |
| 
 | |
|         if ((error->domain == XML_FROM_VALID) ||
 | |
|             (error->domain == XML_FROM_DTD)) {
 | |
|             if (error->level == XML_ERR_WARNING)
 | |
|                 severity = XML_PARSER_SEVERITY_VALIDITY_WARNING;
 | |
|             else
 | |
|                 severity = XML_PARSER_SEVERITY_VALIDITY_ERROR;
 | |
|         } else {
 | |
|             if (error->level == XML_ERR_WARNING)
 | |
|                 severity = XML_PARSER_SEVERITY_WARNING;
 | |
|             else
 | |
|                 severity = XML_PARSER_SEVERITY_ERROR;
 | |
|         }
 | |
| 
 | |
|         reader->errorFunc(reader->errorFuncArg, error->message, severity,
 | |
|                           reader->ctxt);
 | |
|     }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderEntPush:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @value:  the entity reference node
 | |
|  *
 | |
|  * Pushes a new entity reference node on top of the entities stack
 | |
|  *
 | |
|  * Returns -1 in case of error, the index in the stack otherwise
 | |
|  */
 | |
| static int
 | |
| xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
 | |
| {
 | |
|     if (reader->entNr >= reader->entMax) {
 | |
|         size_t newSize = reader->entMax == 0 ? 10 : reader->entMax * 2;
 | |
|         xmlNodePtr *tmp;
 | |
| 
 | |
|         tmp = (xmlNodePtr *) xmlRealloc(reader->entTab,
 | |
|                                         newSize * sizeof(*tmp));
 | |
|         if (tmp == NULL) {
 | |
|             xmlTextReaderErrMemory(reader);
 | |
|             return (-1);
 | |
|         }
 | |
|         reader->entTab = tmp;
 | |
|         reader->entMax = newSize;
 | |
|     }
 | |
|     reader->entTab[reader->entNr] = value;
 | |
|     reader->ent = value;
 | |
|     return (reader->entNr++);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderEntPop:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Pops the top element entity from the entities stack
 | |
|  *
 | |
|  * Returns the entity just removed
 | |
|  */
 | |
| static xmlNodePtr
 | |
| xmlTextReaderEntPop(xmlTextReaderPtr reader)
 | |
| {
 | |
|     xmlNodePtr ret;
 | |
| 
 | |
|     if (reader->entNr <= 0)
 | |
|         return (NULL);
 | |
|     reader->entNr--;
 | |
|     if (reader->entNr > 0)
 | |
|         reader->ent = reader->entTab[reader->entNr - 1];
 | |
|     else
 | |
|         reader->ent = NULL;
 | |
|     ret = reader->entTab[reader->entNr];
 | |
|     reader->entTab[reader->entNr] = NULL;
 | |
|     return (ret);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderStartElement:
 | |
|  * @ctx: the user data (XML parser context)
 | |
|  * @fullname:  The element name, including namespace prefix
 | |
|  * @atts:  An array of name/value attributes pairs, NULL terminated
 | |
|  *
 | |
|  * called when an opening tag has been processed.
 | |
|  */
 | |
| static void
 | |
| xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
 | |
| 	                  const xmlChar **atts) {
 | |
|     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
 | |
|     xmlTextReaderPtr reader = ctxt->_private;
 | |
| 
 | |
|     if ((reader != NULL) && (reader->startElement != NULL)) {
 | |
| 	reader->startElement(ctx, fullname, atts);
 | |
| 	if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
 | |
| 	    (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
 | |
| 	    (ctxt->input->cur[1] == '>'))
 | |
| 	    ctxt->node->extra = NODE_IS_EMPTY;
 | |
|     }
 | |
|     if (reader != NULL)
 | |
| 	reader->state = XML_TEXTREADER_ELEMENT;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderEndElement:
 | |
|  * @ctx: the user data (XML parser context)
 | |
|  * @fullname:  The element name, including namespace prefix
 | |
|  *
 | |
|  * called when an ending tag has been processed.
 | |
|  */
 | |
| static void
 | |
| xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
 | |
|     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
 | |
|     xmlTextReaderPtr reader = ctxt->_private;
 | |
| 
 | |
|     if ((reader != NULL) && (reader->endElement != NULL)) {
 | |
| 	reader->endElement(ctx, fullname);
 | |
|     }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderStartElementNs:
 | |
|  * @ctx: the user data (XML parser context)
 | |
|  * @localname:  the local name of the element
 | |
|  * @prefix:  the element namespace prefix if available
 | |
|  * @URI:  the element namespace name if available
 | |
|  * @nb_namespaces:  number of namespace definitions on that node
 | |
|  * @namespaces:  pointer to the array of prefix/URI pairs namespace definitions
 | |
|  * @nb_attributes:  the number of attributes on that node
 | |
|  * nb_defaulted:  the number of defaulted attributes.
 | |
|  * @attributes:  pointer to the array of (localname/prefix/URI/value/end)
 | |
|  *               attribute values.
 | |
|  *
 | |
|  * called when an opening tag has been processed.
 | |
|  */
 | |
| static void
 | |
| xmlTextReaderStartElementNs(void *ctx,
 | |
|                       const xmlChar *localname,
 | |
| 		      const xmlChar *prefix,
 | |
| 		      const xmlChar *URI,
 | |
| 		      int nb_namespaces,
 | |
| 		      const xmlChar **namespaces,
 | |
| 		      int nb_attributes,
 | |
| 		      int nb_defaulted,
 | |
| 		      const xmlChar **attributes)
 | |
| {
 | |
|     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
 | |
|     xmlTextReaderPtr reader = ctxt->_private;
 | |
| 
 | |
|     if ((reader != NULL) && (reader->startElementNs != NULL)) {
 | |
| 	reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
 | |
| 	                       namespaces, nb_attributes, nb_defaulted,
 | |
| 			       attributes);
 | |
| 	if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
 | |
| 	    (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
 | |
| 	    (ctxt->input->cur[1] == '>'))
 | |
| 	    ctxt->node->extra = NODE_IS_EMPTY;
 | |
|     }
 | |
|     if (reader != NULL)
 | |
| 	reader->state = XML_TEXTREADER_ELEMENT;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderEndElementNs:
 | |
|  * @ctx: the user data (XML parser context)
 | |
|  * @localname:  the local name of the element
 | |
|  * @prefix:  the element namespace prefix if available
 | |
|  * @URI:  the element namespace name if available
 | |
|  *
 | |
|  * called when an ending tag has been processed.
 | |
|  */
 | |
| static void
 | |
| xmlTextReaderEndElementNs(void *ctx,
 | |
|                           const xmlChar * localname,
 | |
|                           const xmlChar * prefix,
 | |
| 		          const xmlChar * URI)
 | |
| {
 | |
|     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
 | |
|     xmlTextReaderPtr reader = ctxt->_private;
 | |
| 
 | |
|     if ((reader != NULL) && (reader->endElementNs != NULL)) {
 | |
| 	reader->endElementNs(ctx, localname, prefix, URI);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderCharacters:
 | |
|  * @ctx: the user data (XML parser context)
 | |
|  * @ch:  a xmlChar string
 | |
|  * @len: the number of xmlChar
 | |
|  *
 | |
|  * receiving some chars from the parser.
 | |
|  */
 | |
| static void
 | |
| xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
 | |
| {
 | |
|     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
 | |
|     xmlTextReaderPtr reader = ctxt->_private;
 | |
| 
 | |
|     if ((reader != NULL) && (reader->characters != NULL)) {
 | |
| 	reader->characters(ctx, ch, len);
 | |
|     }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderCDataBlock:
 | |
|  * @ctx: the user data (XML parser context)
 | |
|  * @value:  The pcdata content
 | |
|  * @len:  the block length
 | |
|  *
 | |
|  * called when a pcdata block has been parsed
 | |
|  */
 | |
| static void
 | |
| xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
 | |
| {
 | |
|     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
 | |
|     xmlTextReaderPtr reader = ctxt->_private;
 | |
| 
 | |
|     if ((reader != NULL) && (reader->cdataBlock != NULL)) {
 | |
| 	reader->cdataBlock(ctx, ch, len);
 | |
|     }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderPushData:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Push data down the progressive parser until a significant callback
 | |
|  * got raised.
 | |
|  *
 | |
|  * Returns -1 in case of failure, 0 otherwise
 | |
|  */
 | |
| static int
 | |
| xmlTextReaderPushData(xmlTextReaderPtr reader) {
 | |
|     xmlBufPtr inbuf;
 | |
|     int val, s;
 | |
|     xmlTextReaderState oldstate;
 | |
| 
 | |
|     if ((reader->input == NULL) || (reader->input->buffer == NULL))
 | |
| 	return(-1);
 | |
| 
 | |
|     oldstate = reader->state;
 | |
|     reader->state = XML_TEXTREADER_NONE;
 | |
|     inbuf = reader->input->buffer;
 | |
| 
 | |
|     while (reader->state == XML_TEXTREADER_NONE) {
 | |
| 	if (xmlBufUse(inbuf) < reader->cur + CHUNK_SIZE) {
 | |
| 	    /*
 | |
| 	     * Refill the buffer unless we are at the end of the stream
 | |
| 	     */
 | |
| 	    if (reader->mode != XML_TEXTREADER_MODE_EOF) {
 | |
| 		val = xmlParserInputBufferRead(reader->input, 4096);
 | |
| 		if (val == 0) {
 | |
| 		    if (xmlBufUse(inbuf) == reader->cur) {
 | |
| 			reader->mode = XML_TEXTREADER_MODE_EOF;
 | |
|                         break;
 | |
| 		    }
 | |
| 		} else if (val < 0) {
 | |
|                     xmlCtxtErrIO(reader->ctxt, reader->input->error, NULL);
 | |
|                     reader->mode = XML_TEXTREADER_MODE_ERROR;
 | |
|                     reader->state = XML_TEXTREADER_ERROR;
 | |
|                     return(-1);
 | |
| 		}
 | |
| 
 | |
| 	    } else
 | |
| 		break;
 | |
| 	}
 | |
| 	/*
 | |
| 	 * parse by block of CHUNK_SIZE bytes, various tests show that
 | |
| 	 * it's the best tradeoff at least on a 1.2GH Duron
 | |
| 	 */
 | |
| 	if (xmlBufUse(inbuf) >= reader->cur + CHUNK_SIZE) {
 | |
| 	    val = xmlParseChunk(reader->ctxt,
 | |
|                  (const char *) xmlBufContent(inbuf) + reader->cur,
 | |
|                                 CHUNK_SIZE, 0);
 | |
| 	    reader->cur += CHUNK_SIZE;
 | |
| 	    if (val != 0)
 | |
| 		reader->ctxt->wellFormed = 0;
 | |
| 	    if (reader->ctxt->wellFormed == 0)
 | |
| 		break;
 | |
| 	} else {
 | |
| 	    s = xmlBufUse(inbuf) - reader->cur;
 | |
| 	    val = xmlParseChunk(reader->ctxt,
 | |
| 		 (const char *) xmlBufContent(inbuf) + reader->cur,
 | |
| 			        s, 0);
 | |
| 	    reader->cur += s;
 | |
| 	    if (val != 0)
 | |
| 		reader->ctxt->wellFormed = 0;
 | |
| 	    break;
 | |
| 	}
 | |
|     }
 | |
|     reader->state = oldstate;
 | |
| 
 | |
|     /*
 | |
|      * Discard the consumed input when needed and possible
 | |
|      */
 | |
|     if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
 | |
|         if (reader->cur > 80 /* LINE_LEN */) {
 | |
|             val = xmlBufShrink(inbuf, reader->cur - 80);
 | |
|             if (val >= 0) {
 | |
|                 reader->cur -= val;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /*
 | |
|      * At the end of the stream signal that the work is done to the Push
 | |
|      * parser.
 | |
|      */
 | |
|     else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
 | |
| 	if (reader->state != XML_TEXTREADER_DONE) {
 | |
| 	    s = xmlBufUse(inbuf) - reader->cur;
 | |
| 	    val = xmlParseChunk(reader->ctxt,
 | |
| 		 (const char *) xmlBufContent(inbuf) + reader->cur,
 | |
| 			        s, 1);
 | |
| 	    reader->cur = xmlBufUse(inbuf);
 | |
| 	    reader->state  = XML_TEXTREADER_DONE;
 | |
| 	    if (val != 0) {
 | |
| 	        if (reader->ctxt->wellFormed)
 | |
| 		    reader->ctxt->wellFormed = 0;
 | |
| 		else
 | |
| 		    return(-1);
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
|     if (reader->ctxt->wellFormed == 0) {
 | |
| 	reader->mode = XML_TEXTREADER_MODE_EOF;
 | |
|         return(-1);
 | |
|     }
 | |
| 
 | |
|     return(0);
 | |
| }
 | |
| 
 | |
| #ifdef LIBXML_REGEXP_ENABLED
 | |
| /**
 | |
|  * xmlTextReaderValidatePush:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Push the current node for validation
 | |
|  */
 | |
| static int
 | |
| xmlTextReaderValidatePush(xmlTextReaderPtr reader) {
 | |
|     xmlNodePtr node = reader->node;
 | |
| 
 | |
| #ifdef LIBXML_VALID_ENABLED
 | |
|     if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
 | |
|         (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
 | |
| 	if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
 | |
| 	    reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
 | |
| 				    reader->ctxt->myDoc, node, node->name);
 | |
| 	} else {
 | |
|             xmlChar buf[50];
 | |
| 	    xmlChar *qname;
 | |
| 
 | |
| 	    qname = xmlBuildQName(node->name, node->ns->prefix, buf, 50);
 | |
|             if (qname == NULL) {
 | |
|                 xmlTextReaderErrMemory(reader);
 | |
|                 return(-1);
 | |
|             }
 | |
| 	    reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
 | |
| 				    reader->ctxt->myDoc, node, qname);
 | |
|             if (qname != buf)
 | |
| 	        xmlFree(qname);
 | |
| 	}
 | |
|         /*if (reader->ctxt->errNo == XML_ERR_NO_MEMORY) {
 | |
|             reader->mode = XML_TEXTREADER_MODE_ERROR;
 | |
|             reader->state = XML_TEXTREADER_ERROR;
 | |
|             return(-1);
 | |
|         }*/
 | |
|     }
 | |
| #endif /* LIBXML_VALID_ENABLED */
 | |
| #ifdef LIBXML_SCHEMAS_ENABLED
 | |
|     if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
 | |
|                (reader->rngValidCtxt != NULL)) {
 | |
| 	int ret;
 | |
| 
 | |
| 	if (reader->rngFullNode != NULL) return(0);
 | |
| 	ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
 | |
| 	                                    reader->ctxt->myDoc,
 | |
| 					    node);
 | |
| 	if (ret == 0) {
 | |
| 	    /*
 | |
| 	     * this element requires a full tree
 | |
| 	     */
 | |
| 	    node = xmlTextReaderExpand(reader);
 | |
| 	    if (node == NULL) {
 | |
| 	        ret = -1;
 | |
| 	    } else {
 | |
| 		ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
 | |
| 						    reader->ctxt->myDoc,
 | |
| 						    node);
 | |
| 		reader->rngFullNode = node;
 | |
| 	    }
 | |
| 	}
 | |
| 	if (ret != 1)
 | |
| 	    reader->rngValidErrors++;
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     return(0);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderValidateCData:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @data:  pointer to the CData
 | |
|  * @len:  length of the CData block in bytes.
 | |
|  *
 | |
|  * Push some CData for validation
 | |
|  */
 | |
| static void
 | |
| xmlTextReaderValidateCData(xmlTextReaderPtr reader,
 | |
|                            const xmlChar *data, int len) {
 | |
| #ifdef LIBXML_VALID_ENABLED
 | |
|     if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
 | |
|         (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
 | |
| 	reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
 | |
| 	                                            data, len);
 | |
|     }
 | |
| #endif /* LIBXML_VALID_ENABLED */
 | |
| #ifdef LIBXML_SCHEMAS_ENABLED
 | |
|     if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
 | |
|                (reader->rngValidCtxt != NULL)) {
 | |
| 	int ret;
 | |
| 
 | |
| 	if (reader->rngFullNode != NULL) return;
 | |
| 	ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
 | |
| 	if (ret != 1)
 | |
| 	    reader->rngValidErrors++;
 | |
|     }
 | |
| #endif
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderValidatePop:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Pop the current node from validation
 | |
|  */
 | |
| static int
 | |
| xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
 | |
|     xmlNodePtr node = reader->node;
 | |
| 
 | |
| #ifdef LIBXML_VALID_ENABLED
 | |
|     if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
 | |
|         (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
 | |
| 	if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
 | |
| 	    reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
 | |
| 				    reader->ctxt->myDoc, node, node->name);
 | |
| 	} else {
 | |
|             xmlChar buf[50];
 | |
| 	    xmlChar *qname;
 | |
| 
 | |
| 	    qname = xmlBuildQName(node->name, node->ns->prefix, buf, 50);
 | |
|             if (qname == NULL) {
 | |
|                 xmlTextReaderErrMemory(reader);
 | |
|                 return(-1);
 | |
|             }
 | |
| 	    reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
 | |
| 				    reader->ctxt->myDoc, node, qname);
 | |
|             if (qname != buf)
 | |
| 	        xmlFree(qname);
 | |
| 	}
 | |
|         /*if (reader->ctxt->errNo == XML_ERR_NO_MEMORY) {
 | |
|             reader->mode = XML_TEXTREADER_MODE_ERROR;
 | |
|             reader->state = XML_TEXTREADER_ERROR;
 | |
|             return(-1);
 | |
|         }*/
 | |
|     }
 | |
| #endif /* LIBXML_VALID_ENABLED */
 | |
| #ifdef LIBXML_SCHEMAS_ENABLED
 | |
|     if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
 | |
|                (reader->rngValidCtxt != NULL)) {
 | |
| 	int ret;
 | |
| 
 | |
| 	if (reader->rngFullNode != NULL) {
 | |
| 	    if (node == reader->rngFullNode)
 | |
| 	        reader->rngFullNode = NULL;
 | |
| 	    return(0);
 | |
| 	}
 | |
| 	ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
 | |
| 	                                   reader->ctxt->myDoc,
 | |
| 					   node);
 | |
| 	if (ret != 1)
 | |
| 	    reader->rngValidErrors++;
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     return(0);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderValidateEntity:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Handle the validation when an entity reference is encountered and
 | |
|  * entity substitution is not activated. As a result the parser interface
 | |
|  * must walk through the entity and do the validation calls
 | |
|  */
 | |
| static int
 | |
| xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
 | |
|     xmlNodePtr oldnode = reader->node;
 | |
|     xmlNodePtr node = reader->node;
 | |
| 
 | |
|     do {
 | |
| 	if (node->type == XML_ENTITY_REF_NODE) {
 | |
| 	    if ((node->children != NULL) &&
 | |
| 		(node->children->type == XML_ENTITY_DECL) &&
 | |
| 		(node->children->children != NULL)) {
 | |
| 		if (xmlTextReaderEntPush(reader, node) < 0) {
 | |
|                     if (node == oldnode)
 | |
|                         break;
 | |
|                     goto skip_children;
 | |
|                 }
 | |
| 		node = node->children->children;
 | |
| 		continue;
 | |
| 	    } else {
 | |
| 		/*
 | |
| 		 * The error has probably been raised already.
 | |
| 		 */
 | |
| 		if (node == oldnode)
 | |
| 		    break;
 | |
|                 goto skip_children;
 | |
| 	    }
 | |
| #ifdef LIBXML_REGEXP_ENABLED
 | |
| 	} else if (node->type == XML_ELEMENT_NODE) {
 | |
| 	    reader->node = node;
 | |
| 	    if (xmlTextReaderValidatePush(reader) < 0)
 | |
|                 return(-1);
 | |
| 	} else if ((node->type == XML_TEXT_NODE) ||
 | |
| 		   (node->type == XML_CDATA_SECTION_NODE)) {
 | |
|             xmlTextReaderValidateCData(reader, node->content,
 | |
| 	                               xmlStrlen(node->content));
 | |
| #endif
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	 * go to next node
 | |
| 	 */
 | |
| 	if (node->children != NULL) {
 | |
| 	    node = node->children;
 | |
| 	    continue;
 | |
| 	} else if (node->type == XML_ELEMENT_NODE) {
 | |
| 	    if (xmlTextReaderValidatePop(reader) < 0)
 | |
|                 return(-1);
 | |
| 	}
 | |
| skip_children:
 | |
| 	if (node->next != NULL) {
 | |
| 	    node = node->next;
 | |
| 	    continue;
 | |
| 	}
 | |
| 	do {
 | |
| 	    node = node->parent;
 | |
| 	    if (node->type == XML_ELEMENT_NODE) {
 | |
| 	        xmlNodePtr tmp;
 | |
| 		if (reader->entNr == 0) {
 | |
| 		    while ((tmp = node->last) != NULL) {
 | |
| 			if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
 | |
| 			    xmlUnlinkNode(tmp);
 | |
| 			    xmlTextReaderFreeNode(reader, tmp);
 | |
| 			} else
 | |
| 			    break;
 | |
| 		    }
 | |
| 		}
 | |
| 		reader->node = node;
 | |
| 		if (xmlTextReaderValidatePop(reader) < 0)
 | |
|                     return(-1);
 | |
| 	    }
 | |
| 	    if ((node->type == XML_ENTITY_DECL) &&
 | |
| 		(reader->ent != NULL) && (reader->ent->children == node)) {
 | |
| 		node = xmlTextReaderEntPop(reader);
 | |
| 	    }
 | |
| 	    if (node == oldnode)
 | |
| 		break;
 | |
| 	    if (node->next != NULL) {
 | |
| 		node = node->next;
 | |
| 		break;
 | |
| 	    }
 | |
| 	} while ((node != NULL) && (node != oldnode));
 | |
|     } while ((node != NULL) && (node != oldnode));
 | |
|     reader->node = oldnode;
 | |
| 
 | |
|     return(0);
 | |
| }
 | |
| #endif /* LIBXML_REGEXP_ENABLED */
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderGetSuccessor:
 | |
|  * @cur:  the current node
 | |
|  *
 | |
|  * Get the successor of a node if available.
 | |
|  *
 | |
|  * Returns the successor node or NULL
 | |
|  */
 | |
| static xmlNodePtr
 | |
| xmlTextReaderGetSuccessor(xmlNodePtr cur) {
 | |
|     if (cur == NULL) return(NULL) ; /* ERROR */
 | |
|     if (cur->next != NULL) return(cur->next) ;
 | |
|     do {
 | |
|         cur = cur->parent;
 | |
|         if (cur == NULL) break;
 | |
|         if (cur->next != NULL) return(cur->next);
 | |
|     } while (cur != NULL);
 | |
|     return(cur);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderDoExpand:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Makes sure that the current node is fully read as well as all its
 | |
|  * descendant. It means the full DOM subtree must be available at the
 | |
|  * end of the call.
 | |
|  *
 | |
|  * Returns 1 if the node was expanded successfully, 0 if there is no more
 | |
|  *          nodes to read, or -1 in case of error
 | |
|  */
 | |
| static int
 | |
| xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
 | |
|     int val;
 | |
| 
 | |
|     if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
 | |
|         return(-1);
 | |
|     do {
 | |
| 	if (PARSER_STOPPED(reader->ctxt))
 | |
|             return(1);
 | |
| 
 | |
|         if (xmlTextReaderGetSuccessor(reader->node) != NULL)
 | |
| 	    return(1);
 | |
| 	if (reader->ctxt->nodeNr < reader->depth)
 | |
| 	    return(1);
 | |
| 	if (reader->mode == XML_TEXTREADER_MODE_EOF)
 | |
| 	    return(1);
 | |
| 	val = xmlTextReaderPushData(reader);
 | |
| 	if (val < 0){
 | |
| 	    reader->mode = XML_TEXTREADER_MODE_ERROR;
 | |
|             reader->state = XML_TEXTREADER_ERROR;
 | |
| 	    return(-1);
 | |
| 	}
 | |
|     } while(reader->mode != XML_TEXTREADER_MODE_EOF);
 | |
|     return(1);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderRead:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  *  Moves the position of the current instance to the next node in
 | |
|  *  the stream, exposing its properties.
 | |
|  *
 | |
|  *  Returns 1 if the node was read successfully, 0 if there is no more
 | |
|  *          nodes to read, or -1 in case of error
 | |
|  */
 | |
| int
 | |
| xmlTextReaderRead(xmlTextReaderPtr reader) {
 | |
|     int val, olddepth = 0;
 | |
|     xmlTextReaderState oldstate = XML_TEXTREADER_START;
 | |
|     xmlNodePtr oldnode = NULL;
 | |
| 
 | |
|     if (reader == NULL)
 | |
| 	return(-1);
 | |
|     if (reader->state == XML_TEXTREADER_ERROR)
 | |
|         return(-1);
 | |
| 
 | |
|     reader->curnode = NULL;
 | |
|     if (reader->doc != NULL)
 | |
|         return(xmlTextReaderReadTree(reader));
 | |
|     if (reader->ctxt == NULL)
 | |
| 	return(-1);
 | |
| 
 | |
|     if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
 | |
| 	reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
 | |
| 	/*
 | |
| 	 * Initial state
 | |
| 	 */
 | |
| 	do {
 | |
| 	    val = xmlTextReaderPushData(reader);
 | |
|             if (val < 0) {
 | |
|                 reader->mode = XML_TEXTREADER_MODE_ERROR;
 | |
|                 reader->state = XML_TEXTREADER_ERROR;
 | |
|                 return(-1);
 | |
|             }
 | |
| 	} while ((reader->ctxt->node == NULL) &&
 | |
| 		 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
 | |
| 		  (reader->state != XML_TEXTREADER_DONE)));
 | |
| 	if (reader->ctxt->node == NULL) {
 | |
| 	    if (reader->ctxt->myDoc != NULL) {
 | |
| 		reader->node = reader->ctxt->myDoc->children;
 | |
| 	    }
 | |
| 	    if (reader->node == NULL) {
 | |
|                 reader->mode = XML_TEXTREADER_MODE_ERROR;
 | |
|                 reader->state = XML_TEXTREADER_ERROR;
 | |
| 		return(-1);
 | |
| 	    }
 | |
| 	    reader->state = XML_TEXTREADER_ELEMENT;
 | |
| 	} else {
 | |
| 	    if (reader->ctxt->myDoc != NULL) {
 | |
| 		reader->node = reader->ctxt->myDoc->children;
 | |
| 	    }
 | |
| 	    if (reader->node == NULL)
 | |
| 		reader->node = reader->ctxt->nodeTab[0];
 | |
| 	    reader->state = XML_TEXTREADER_ELEMENT;
 | |
| 	}
 | |
| 	reader->depth = 0;
 | |
| 	reader->ctxt->parseMode = XML_PARSE_READER;
 | |
| 	goto node_found;
 | |
|     }
 | |
|     oldstate = reader->state;
 | |
|     olddepth = reader->ctxt->nodeNr;
 | |
|     oldnode = reader->node;
 | |
| 
 | |
| get_next_node:
 | |
|     if (reader->node == NULL) {
 | |
| 	if (reader->mode == XML_TEXTREADER_MODE_EOF) {
 | |
| 	    return(0);
 | |
|         } else {
 | |
|             reader->mode = XML_TEXTREADER_MODE_ERROR;
 | |
|             reader->state = XML_TEXTREADER_ERROR;
 | |
| 	    return(-1);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /*
 | |
|      * If we are not backtracking on ancestors or examined nodes,
 | |
|      * that the parser didn't finished or that we aren't at the end
 | |
|      * of stream, continue processing.
 | |
|      */
 | |
|     while ((reader->node != NULL) && (reader->node->next == NULL) &&
 | |
| 	   (reader->ctxt->nodeNr == olddepth) &&
 | |
|            ((oldstate == XML_TEXTREADER_BACKTRACK) ||
 | |
|             (reader->node->children == NULL) ||
 | |
| 	    (reader->node->type == XML_ENTITY_REF_NODE) ||
 | |
| 	    ((reader->node->children != NULL) &&
 | |
| 	     (reader->node->children->type == XML_TEXT_NODE) &&
 | |
| 	     (reader->node->children->next == NULL)) ||
 | |
| 	    (reader->node->type == XML_DTD_NODE) ||
 | |
| 	    (reader->node->type == XML_DOCUMENT_NODE) ||
 | |
| 	    (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
 | |
| 	   ((reader->ctxt->node == NULL) ||
 | |
| 	    (reader->ctxt->node == reader->node) ||
 | |
| 	    (reader->ctxt->node == reader->node->parent)) &&
 | |
| 	   (reader->ctxt->instate != XML_PARSER_EOF) &&
 | |
| 	   (PARSER_STOPPED(reader->ctxt) == 0)) {
 | |
| 	val = xmlTextReaderPushData(reader);
 | |
| 	if (val < 0) {
 | |
|             reader->mode = XML_TEXTREADER_MODE_ERROR;
 | |
|             reader->state = XML_TEXTREADER_ERROR;
 | |
| 	    return(-1);
 | |
|         }
 | |
| 	if (reader->node == NULL)
 | |
| 	    goto node_end;
 | |
|     }
 | |
|     if (oldstate != XML_TEXTREADER_BACKTRACK) {
 | |
| 	if ((reader->node->children != NULL) &&
 | |
| 	    (reader->node->type != XML_ENTITY_REF_NODE) &&
 | |
| 	    (reader->node->type != XML_XINCLUDE_START) &&
 | |
| 	    (reader->node->type != XML_DTD_NODE)) {
 | |
| 	    reader->node = reader->node->children;
 | |
| 	    reader->depth++;
 | |
| 	    reader->state = XML_TEXTREADER_ELEMENT;
 | |
| 	    goto node_found;
 | |
| 	}
 | |
|     }
 | |
|     if (reader->node->next != NULL) {
 | |
| 	if ((oldstate == XML_TEXTREADER_ELEMENT) &&
 | |
|             (reader->node->type == XML_ELEMENT_NODE) &&
 | |
| 	    (reader->node->children == NULL) &&
 | |
| 	    ((reader->node->extra & NODE_IS_EMPTY) == 0)
 | |
| #ifdef LIBXML_XINCLUDE_ENABLED
 | |
| 	    && (reader->in_xinclude <= 0)
 | |
| #endif
 | |
| 	    ) {
 | |
| 	    reader->state = XML_TEXTREADER_END;
 | |
| 	    goto node_found;
 | |
| 	}
 | |
| #ifdef LIBXML_REGEXP_ENABLED
 | |
| 	if ((reader->validate) &&
 | |
| 	    (reader->node->type == XML_ELEMENT_NODE))
 | |
| 	    if (xmlTextReaderValidatePop(reader) < 0)
 | |
|                 return(-1);
 | |
| #endif /* LIBXML_REGEXP_ENABLED */
 | |
|         if ((reader->preserves > 0) &&
 | |
| 	    (reader->node->extra & NODE_IS_SPRESERVED))
 | |
| 	    reader->preserves--;
 | |
| 	reader->node = reader->node->next;
 | |
| 	reader->state = XML_TEXTREADER_ELEMENT;
 | |
| 
 | |
| 	/*
 | |
| 	 * Cleanup of the old node
 | |
| 	 */
 | |
| 	if ((reader->preserves == 0) &&
 | |
| #ifdef LIBXML_XINCLUDE_ENABLED
 | |
| 	    (reader->in_xinclude == 0) &&
 | |
| #endif
 | |
| 	    (reader->entNr == 0) &&
 | |
| 	    (reader->node->prev != NULL) &&
 | |
|             (reader->node->prev->type != XML_DTD_NODE)) {
 | |
| 	    xmlNodePtr tmp = reader->node->prev;
 | |
| 	    if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
 | |
|                 if (oldnode == tmp)
 | |
|                     oldnode = NULL;
 | |
| 		xmlUnlinkNode(tmp);
 | |
| 		xmlTextReaderFreeNode(reader, tmp);
 | |
| 	    }
 | |
| 	}
 | |
| 
 | |
| 	goto node_found;
 | |
|     }
 | |
|     if ((oldstate == XML_TEXTREADER_ELEMENT) &&
 | |
| 	(reader->node->type == XML_ELEMENT_NODE) &&
 | |
| 	(reader->node->children == NULL) &&
 | |
| 	((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
 | |
| 	reader->state = XML_TEXTREADER_END;
 | |
| 	goto node_found;
 | |
|     }
 | |
| #ifdef LIBXML_REGEXP_ENABLED
 | |
|     if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) &&
 | |
|         (reader->node->type == XML_ELEMENT_NODE)) {
 | |
|         if (xmlTextReaderValidatePop(reader) < 0)
 | |
|             return(-1);
 | |
|     }
 | |
| #endif /* LIBXML_REGEXP_ENABLED */
 | |
|     if ((reader->preserves > 0) &&
 | |
| 	(reader->node->extra & NODE_IS_SPRESERVED))
 | |
| 	reader->preserves--;
 | |
|     reader->node = reader->node->parent;
 | |
|     if ((reader->node == NULL) ||
 | |
| 	(reader->node->type == XML_DOCUMENT_NODE) ||
 | |
| 	(reader->node->type == XML_HTML_DOCUMENT_NODE)) {
 | |
| 	if (reader->mode != XML_TEXTREADER_MODE_EOF) {
 | |
| 	    val = xmlParseChunk(reader->ctxt, "", 0, 1);
 | |
| 	    reader->state = XML_TEXTREADER_DONE;
 | |
| 	    if (val != 0) {
 | |
|                 reader->mode = XML_TEXTREADER_MODE_ERROR;
 | |
|                 reader->state = XML_TEXTREADER_ERROR;
 | |
| 	        return(-1);
 | |
|             }
 | |
| 	}
 | |
| 	reader->node = NULL;
 | |
| 	reader->depth = -1;
 | |
| 
 | |
| 	/*
 | |
| 	 * Cleanup of the old node
 | |
| 	 */
 | |
| 	if ((oldnode != NULL) && (reader->preserves == 0) &&
 | |
| #ifdef LIBXML_XINCLUDE_ENABLED
 | |
| 	    (reader->in_xinclude == 0) &&
 | |
| #endif
 | |
| 	    (reader->entNr == 0) &&
 | |
| 	    (oldnode->type != XML_DTD_NODE) &&
 | |
| 	    ((oldnode->extra & NODE_IS_PRESERVED) == 0)) {
 | |
| 	    xmlUnlinkNode(oldnode);
 | |
| 	    xmlTextReaderFreeNode(reader, oldnode);
 | |
| 	}
 | |
| 
 | |
| 	goto node_end;
 | |
|     }
 | |
|     if ((reader->preserves == 0) &&
 | |
| #ifdef LIBXML_XINCLUDE_ENABLED
 | |
|         (reader->in_xinclude == 0) &&
 | |
| #endif
 | |
| 	(reader->entNr == 0) &&
 | |
|         (reader->node->last != NULL) &&
 | |
|         ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
 | |
| 	xmlNodePtr tmp = reader->node->last;
 | |
| 	xmlUnlinkNode(tmp);
 | |
| 	xmlTextReaderFreeNode(reader, tmp);
 | |
|     }
 | |
|     reader->depth--;
 | |
|     reader->state = XML_TEXTREADER_BACKTRACK;
 | |
| 
 | |
| node_found:
 | |
|     /*
 | |
|      * If we are in the middle of a piece of CDATA make sure it's finished
 | |
|      */
 | |
|     if ((reader->node != NULL) &&
 | |
|         (reader->node->next == NULL) &&
 | |
|         ((reader->node->type == XML_TEXT_NODE) ||
 | |
| 	 (reader->node->type == XML_CDATA_SECTION_NODE))) {
 | |
|             if (xmlTextReaderExpand(reader) == NULL)
 | |
| 	        return -1;
 | |
|     }
 | |
| 
 | |
| #ifdef LIBXML_XINCLUDE_ENABLED
 | |
|     /*
 | |
|      * Handle XInclude if asked for
 | |
|      */
 | |
|     if ((reader->xinclude) && (reader->in_xinclude == 0) &&
 | |
|         (reader->state != XML_TEXTREADER_BACKTRACK) &&
 | |
|         (reader->node != NULL) &&
 | |
| 	(reader->node->type == XML_ELEMENT_NODE) &&
 | |
| 	(reader->node->ns != NULL) &&
 | |
| 	((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
 | |
| 	 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
 | |
| 	if (reader->xincctxt == NULL) {
 | |
| 	    reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
 | |
|             if (reader->xincctxt == NULL) {
 | |
|                 xmlTextReaderErrMemory(reader);
 | |
|                 return(-1);
 | |
|             }
 | |
| 	    xmlXIncludeSetFlags(reader->xincctxt,
 | |
| 	                        reader->parserFlags & (~XML_PARSE_NOXINCNODE));
 | |
|             xmlXIncludeSetStreamingMode(reader->xincctxt, 1);
 | |
|             if ((reader->errorFunc != NULL) || (reader->sErrorFunc != NULL))
 | |
|                 xmlXIncludeSetErrorHandler(reader->xincctxt,
 | |
|                         xmlTextReaderStructuredRelay, reader);
 | |
|             if (reader->resourceLoader != NULL)
 | |
|                 xmlXIncludeSetResourceLoader(reader->xincctxt,
 | |
|                         reader->resourceLoader, reader->resourceCtxt);
 | |
| 	}
 | |
| 	/*
 | |
| 	 * expand that node and process it
 | |
| 	 */
 | |
| 	if (xmlTextReaderExpand(reader) == NULL)
 | |
| 	    return(-1);
 | |
|         if (xmlXIncludeProcessNode(reader->xincctxt, reader->node) < 0) {
 | |
|             int err = xmlXIncludeGetLastError(reader->xincctxt);
 | |
| 
 | |
|             if (err == XML_ERR_NO_MEMORY)
 | |
|                 xmlTextReaderErrMemory(reader);
 | |
|             return(-1);
 | |
|         }
 | |
|     }
 | |
|     if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_START)) {
 | |
|         reader->in_xinclude++;
 | |
| 	goto get_next_node;
 | |
|     }
 | |
|     if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_END)) {
 | |
|         reader->in_xinclude--;
 | |
| 	goto get_next_node;
 | |
|     }
 | |
| #endif
 | |
|     /*
 | |
|      * Handle entities enter and exit when in entity replacement mode
 | |
|      */
 | |
|     if ((reader->node != NULL) &&
 | |
| 	(reader->node->type == XML_ENTITY_REF_NODE) &&
 | |
| 	(reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
 | |
| 	if ((reader->node->children != NULL) &&
 | |
| 	    (reader->node->children->type == XML_ENTITY_DECL) &&
 | |
| 	    (reader->node->children->children != NULL)) {
 | |
| 	    if (xmlTextReaderEntPush(reader, reader->node) < 0)
 | |
|                 goto get_next_node;
 | |
| 	    reader->node = reader->node->children->children;
 | |
| 	}
 | |
| #ifdef LIBXML_REGEXP_ENABLED
 | |
|     } else if ((reader->node != NULL) &&
 | |
| 	       (reader->node->type == XML_ENTITY_REF_NODE) &&
 | |
| 	       (reader->ctxt != NULL) && (reader->validate)) {
 | |
| 	if (xmlTextReaderValidateEntity(reader) < 0)
 | |
|             return(-1);
 | |
| #endif /* LIBXML_REGEXP_ENABLED */
 | |
|     }
 | |
|     if ((reader->node != NULL) &&
 | |
| 	(reader->node->type == XML_ENTITY_DECL) &&
 | |
| 	(reader->ent != NULL) && (reader->ent->children == reader->node)) {
 | |
| 	reader->node = xmlTextReaderEntPop(reader);
 | |
| 	reader->depth++;
 | |
|         goto get_next_node;
 | |
|     }
 | |
| #ifdef LIBXML_REGEXP_ENABLED
 | |
|     if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node != NULL)) {
 | |
| 	xmlNodePtr node = reader->node;
 | |
| 
 | |
| 	if ((node->type == XML_ELEMENT_NODE) &&
 | |
|             ((reader->state != XML_TEXTREADER_END) &&
 | |
| 	     (reader->state != XML_TEXTREADER_BACKTRACK))) {
 | |
| 	    if (xmlTextReaderValidatePush(reader) < 0)
 | |
|                 return(-1);
 | |
| 	} else if ((node->type == XML_TEXT_NODE) ||
 | |
| 		   (node->type == XML_CDATA_SECTION_NODE)) {
 | |
|             xmlTextReaderValidateCData(reader, node->content,
 | |
| 	                               xmlStrlen(node->content));
 | |
| 	}
 | |
|     }
 | |
| #endif /* LIBXML_REGEXP_ENABLED */
 | |
| #ifdef LIBXML_PATTERN_ENABLED
 | |
|     if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
 | |
|         (reader->state != XML_TEXTREADER_BACKTRACK)) {
 | |
|         int i;
 | |
| 	for (i = 0;i < reader->patternNr;i++) {
 | |
| 	     if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
 | |
| 	         xmlTextReaderPreserve(reader);
 | |
| 		 break;
 | |
|              }
 | |
| 	}
 | |
|     }
 | |
| #endif /* LIBXML_PATTERN_ENABLED */
 | |
| #ifdef LIBXML_SCHEMAS_ENABLED
 | |
|     if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) &&
 | |
|         (reader->xsdValidErrors == 0) &&
 | |
| 	(reader->xsdValidCtxt != NULL)) {
 | |
| 	reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt);
 | |
|     }
 | |
| #endif /* LIBXML_PATTERN_ENABLED */
 | |
|     return(1);
 | |
| node_end:
 | |
|     reader->state = XML_TEXTREADER_DONE;
 | |
|     return(0);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderReadState:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Gets the read state of the reader.
 | |
|  *
 | |
|  * Returns the state value, or -1 in case of error
 | |
|  */
 | |
| int
 | |
| xmlTextReaderReadState(xmlTextReaderPtr reader) {
 | |
|     if (reader == NULL)
 | |
| 	return(-1);
 | |
|     return(reader->mode);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderExpand:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Reads the contents of the current node and the full subtree. It then makes
 | |
|  * the subtree available until the next xmlTextReaderRead() call
 | |
|  *
 | |
|  * Returns a node pointer valid until the next xmlTextReaderRead() call
 | |
|  *         or NULL in case of error.
 | |
|  */
 | |
| xmlNodePtr
 | |
| xmlTextReaderExpand(xmlTextReaderPtr reader) {
 | |
|     if ((reader == NULL) || (reader->node == NULL))
 | |
|         return(NULL);
 | |
|     if (reader->doc != NULL)
 | |
|         return(reader->node);
 | |
|     if (reader->ctxt == NULL)
 | |
|         return(NULL);
 | |
|     if (xmlTextReaderDoExpand(reader) < 0)
 | |
|         return(NULL);
 | |
|     return(reader->node);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderNext:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Skip to the node following the current one in document order while
 | |
|  * avoiding the subtree if any.
 | |
|  *
 | |
|  * Returns 1 if the node was read successfully, 0 if there is no more
 | |
|  *          nodes to read, or -1 in case of error
 | |
|  */
 | |
| int
 | |
| xmlTextReaderNext(xmlTextReaderPtr reader) {
 | |
|     int ret;
 | |
|     xmlNodePtr cur;
 | |
| 
 | |
|     if (reader == NULL)
 | |
| 	return(-1);
 | |
|     if (reader->doc != NULL)
 | |
|         return(xmlTextReaderNextTree(reader));
 | |
|     cur = reader->node;
 | |
|     if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
 | |
|         return(xmlTextReaderRead(reader));
 | |
|     if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
 | |
|         return(xmlTextReaderRead(reader));
 | |
|     if (cur->extra & NODE_IS_EMPTY)
 | |
|         return(xmlTextReaderRead(reader));
 | |
|     do {
 | |
|         ret = xmlTextReaderRead(reader);
 | |
| 	if (ret != 1)
 | |
| 	    return(ret);
 | |
|     } while (reader->node != cur);
 | |
|     return(xmlTextReaderRead(reader));
 | |
| }
 | |
| 
 | |
| #ifdef LIBXML_WRITER_ENABLED
 | |
| static void
 | |
| xmlTextReaderDumpCopy(xmlTextReaderPtr reader, xmlOutputBufferPtr output,
 | |
|                       xmlNodePtr node) {
 | |
|     if ((node->type == XML_DTD_NODE) ||
 | |
|         (node->type == XML_ELEMENT_DECL) ||
 | |
|         (node->type == XML_ATTRIBUTE_DECL) ||
 | |
|         (node->type == XML_ENTITY_DECL))
 | |
|         return;
 | |
| 
 | |
|     if ((node->type == XML_DOCUMENT_NODE) ||
 | |
|         (node->type == XML_HTML_DOCUMENT_NODE)) {
 | |
|         xmlNodeDumpOutput(output, node->doc, node, 0, 0, NULL);
 | |
|     } else {
 | |
|         xmlNodePtr copy;
 | |
| 
 | |
|         /*
 | |
|          * Create a copy to make sure that namespace declarations from
 | |
|          * ancestors are added.
 | |
|          */
 | |
|         copy = xmlDocCopyNode(node, node->doc, 1);
 | |
|         if (copy == NULL) {
 | |
|             xmlTextReaderErrMemory(reader);
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         xmlNodeDumpOutput(output, copy->doc, copy, 0, 0, NULL);
 | |
| 
 | |
|         xmlFreeNode(copy);
 | |
|     }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderReadInnerXml:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Reads the contents of the current node, including child nodes and markup.
 | |
|  *
 | |
|  * Returns a string containing the XML content, or NULL if the current node
 | |
|  *         is neither an element nor attribute, or has no child nodes. The
 | |
|  *         string must be deallocated by the caller.
 | |
|  */
 | |
| xmlChar *
 | |
| xmlTextReaderReadInnerXml(xmlTextReaderPtr reader)
 | |
| {
 | |
|     xmlOutputBufferPtr output;
 | |
|     xmlNodePtr cur;
 | |
|     xmlChar *ret;
 | |
| 
 | |
|     if (xmlTextReaderExpand(reader) == NULL)
 | |
|         return(NULL);
 | |
| 
 | |
|     if (reader->node == NULL)
 | |
|         return(NULL);
 | |
| 
 | |
|     output = xmlAllocOutputBuffer(NULL);
 | |
|     if (output == NULL) {
 | |
|         xmlTextReaderErrMemory(reader);
 | |
|         return(NULL);
 | |
|     }
 | |
| 
 | |
|     for (cur = reader->node->children; cur != NULL; cur = cur->next)
 | |
|         xmlTextReaderDumpCopy(reader, output, cur);
 | |
| 
 | |
|     if (output->error)
 | |
|         xmlCtxtErrIO(reader->ctxt, output->error, NULL);
 | |
| 
 | |
|     ret = xmlBufDetach(output->buffer);
 | |
|     xmlOutputBufferClose(output);
 | |
| 
 | |
|     return(ret);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderReadOuterXml:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Reads the contents of the current node, including child nodes and markup.
 | |
|  *
 | |
|  * Returns a string containing the node and any XML content, or NULL if the
 | |
|  *         current node cannot be serialized. The string must be deallocated
 | |
|  *         by the caller.
 | |
|  */
 | |
| xmlChar *
 | |
| xmlTextReaderReadOuterXml(xmlTextReaderPtr reader)
 | |
| {
 | |
|     xmlOutputBufferPtr output;
 | |
|     xmlNodePtr node;
 | |
|     xmlChar *ret;
 | |
| 
 | |
|     if (xmlTextReaderExpand(reader) == NULL)
 | |
|         return(NULL);
 | |
| 
 | |
|     node = reader->node;
 | |
|     if (node == NULL)
 | |
|         return(NULL);
 | |
| 
 | |
|     output = xmlAllocOutputBuffer(NULL);
 | |
|     if (output == NULL) {
 | |
|         xmlTextReaderErrMemory(reader);
 | |
|         return(NULL);
 | |
|     }
 | |
| 
 | |
|     xmlTextReaderDumpCopy(reader, output, node);
 | |
|     if (output->error)
 | |
|         xmlCtxtErrIO(reader->ctxt, output->error, NULL);
 | |
| 
 | |
|     ret = xmlBufDetach(output->buffer);
 | |
|     xmlOutputBufferClose(output);
 | |
| 
 | |
|     return(ret);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderReadString:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Reads the contents of an element or a text node as a string.
 | |
|  *
 | |
|  * Returns a string containing the contents of the Element or Text node,
 | |
|  *         or NULL if the reader is positioned on any other type of node.
 | |
|  *         The string must be deallocated by the caller.
 | |
|  */
 | |
| xmlChar *
 | |
| xmlTextReaderReadString(xmlTextReaderPtr reader)
 | |
| {
 | |
|     xmlNodePtr node, cur;
 | |
|     xmlBufPtr buf;
 | |
|     xmlChar *ret;
 | |
| 
 | |
|     if ((reader == NULL) || (reader->node == NULL))
 | |
|        return(NULL);
 | |
| 
 | |
|     node = (reader->curnode != NULL) ? reader->curnode : reader->node;
 | |
|     switch (node->type) {
 | |
|         case XML_TEXT_NODE:
 | |
|         case XML_CDATA_SECTION_NODE:
 | |
|             break;
 | |
|         case XML_ELEMENT_NODE:
 | |
|             if (xmlTextReaderDoExpand(reader) == -1)
 | |
|                 return(NULL);
 | |
|             break;
 | |
|         case XML_ATTRIBUTE_NODE:
 | |
|             /* TODO */
 | |
|             break;
 | |
|         default:
 | |
|             break;
 | |
|     }
 | |
| 
 | |
|     buf = xmlBufCreate(50);
 | |
|     if (buf == NULL) {
 | |
|         xmlTextReaderErrMemory(reader);
 | |
|         return(NULL);
 | |
|     }
 | |
| 
 | |
|     cur = node;
 | |
|     while (cur != NULL) {
 | |
|         switch (cur->type) {
 | |
|             case XML_TEXT_NODE:
 | |
|             case XML_CDATA_SECTION_NODE:
 | |
|                 xmlBufCat(buf, cur->content);
 | |
|                 break;
 | |
| 
 | |
|             case XML_ELEMENT_NODE:
 | |
|                 if (cur->children != NULL) {
 | |
|                     cur = cur->children;
 | |
|                     continue;
 | |
|                 }
 | |
|                 break;
 | |
| 
 | |
|             default:
 | |
|                 break;
 | |
|         }
 | |
| 
 | |
|         if (cur == node)
 | |
|             goto done;
 | |
| 
 | |
|         while (cur->next == NULL) {
 | |
|             cur = cur->parent;
 | |
|             if (cur == node)
 | |
|                 goto done;
 | |
|         }
 | |
|         cur = cur->next;
 | |
|     }
 | |
| 
 | |
| done:
 | |
|     ret = xmlBufDetach(buf);
 | |
|     if (ret == NULL)
 | |
|         xmlTextReaderErrMemory(reader);
 | |
| 
 | |
|     xmlBufFree(buf);
 | |
|     return(ret);
 | |
| }
 | |
| 
 | |
| /************************************************************************
 | |
|  *									*
 | |
|  *			Operating on a preparsed tree			*
 | |
|  *									*
 | |
|  ************************************************************************/
 | |
| static int
 | |
| xmlTextReaderNextTree(xmlTextReaderPtr reader)
 | |
| {
 | |
|     if (reader == NULL)
 | |
|         return(-1);
 | |
| 
 | |
|     if (reader->state == XML_TEXTREADER_END)
 | |
|         return(0);
 | |
| 
 | |
|     if (reader->node == NULL) {
 | |
|         if (reader->doc->children == NULL) {
 | |
|             reader->state = XML_TEXTREADER_END;
 | |
|             return(0);
 | |
|         }
 | |
| 
 | |
|         reader->node = reader->doc->children;
 | |
|         reader->state = XML_TEXTREADER_START;
 | |
|         return(1);
 | |
|     }
 | |
| 
 | |
|     if (reader->state != XML_TEXTREADER_BACKTRACK) {
 | |
| 	/* Here removed traversal to child, because we want to skip the subtree,
 | |
| 	replace with traversal to sibling to skip subtree */
 | |
|         if (reader->node->next != 0) {
 | |
| 	    /* Move to sibling if present,skipping sub-tree */
 | |
|             reader->node = reader->node->next;
 | |
|             reader->state = XML_TEXTREADER_START;
 | |
|             return(1);
 | |
|         }
 | |
| 
 | |
| 	/* if reader->node->next is NULL mean no subtree for current node,
 | |
| 	so need to move to sibling of parent node if present */
 | |
| 	reader->state = XML_TEXTREADER_BACKTRACK;
 | |
| 	/* This will move to parent if present */
 | |
| 	xmlTextReaderRead(reader);
 | |
|     }
 | |
| 
 | |
|     if (reader->node->next != 0) {
 | |
|         reader->node = reader->node->next;
 | |
|         reader->state = XML_TEXTREADER_START;
 | |
|         return(1);
 | |
|     }
 | |
| 
 | |
|     if (reader->node->parent != 0) {
 | |
|         if (reader->node->parent->type == XML_DOCUMENT_NODE) {
 | |
|             reader->state = XML_TEXTREADER_END;
 | |
|             return(0);
 | |
|         }
 | |
| 
 | |
|         reader->node = reader->node->parent;
 | |
|         reader->depth--;
 | |
|         reader->state = XML_TEXTREADER_BACKTRACK;
 | |
| 	/* Repeat process to move to sibling of parent node if present */
 | |
|         xmlTextReaderNextTree(reader);
 | |
|     }
 | |
| 
 | |
|     reader->state = XML_TEXTREADER_END;
 | |
| 
 | |
|     return(1);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderReadTree:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  *  Moves the position of the current instance to the next node in
 | |
|  *  the stream, exposing its properties.
 | |
|  *
 | |
|  *  Returns 1 if the node was read successfully, 0 if there is no more
 | |
|  *          nodes to read, or -1 in case of error
 | |
|  */
 | |
| static int
 | |
| xmlTextReaderReadTree(xmlTextReaderPtr reader) {
 | |
|     if (reader->state == XML_TEXTREADER_END)
 | |
|         return(0);
 | |
| 
 | |
| next_node:
 | |
|     if (reader->node == NULL) {
 | |
|         if (reader->doc->children == NULL) {
 | |
|             reader->state = XML_TEXTREADER_END;
 | |
|             return(0);
 | |
|         }
 | |
| 
 | |
|         reader->node = reader->doc->children;
 | |
|         reader->state = XML_TEXTREADER_START;
 | |
|         goto found_node;
 | |
|     }
 | |
| 
 | |
|     if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
 | |
|         (reader->node->type != XML_DTD_NODE) &&
 | |
|         (reader->node->type != XML_XINCLUDE_START) &&
 | |
| 	(reader->node->type != XML_ENTITY_REF_NODE)) {
 | |
|         if (reader->node->children != NULL) {
 | |
|             reader->node = reader->node->children;
 | |
|             reader->depth++;
 | |
|             reader->state = XML_TEXTREADER_START;
 | |
|             goto found_node;
 | |
|         }
 | |
| 
 | |
|         if (reader->node->type == XML_ATTRIBUTE_NODE) {
 | |
|             reader->state = XML_TEXTREADER_BACKTRACK;
 | |
|             goto found_node;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (reader->node->next != NULL) {
 | |
|         reader->node = reader->node->next;
 | |
|         reader->state = XML_TEXTREADER_START;
 | |
|         goto found_node;
 | |
|     }
 | |
| 
 | |
|     if (reader->node->parent != NULL) {
 | |
|         if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
 | |
| 	    (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
 | |
|             reader->state = XML_TEXTREADER_END;
 | |
|             return(0);
 | |
|         }
 | |
| 
 | |
|         reader->node = reader->node->parent;
 | |
|         reader->depth--;
 | |
|         reader->state = XML_TEXTREADER_BACKTRACK;
 | |
|         goto found_node;
 | |
|     }
 | |
| 
 | |
|     reader->state = XML_TEXTREADER_END;
 | |
| 
 | |
| found_node:
 | |
|     if ((reader->node->type == XML_XINCLUDE_START) ||
 | |
|         (reader->node->type == XML_XINCLUDE_END))
 | |
| 	goto next_node;
 | |
| 
 | |
|     return(1);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderNextSibling:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Skip to the node following the current one in document order while
 | |
|  * avoiding the subtree if any.
 | |
|  * Currently implemented only for Readers built on a document
 | |
|  *
 | |
|  * Returns 1 if the node was read successfully, 0 if there is no more
 | |
|  *          nodes to read, or -1 in case of error
 | |
|  */
 | |
| int
 | |
| xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
 | |
|     if (reader == NULL)
 | |
|         return(-1);
 | |
|     if (reader->doc == NULL) {
 | |
|         /* TODO */
 | |
| 	return(-1);
 | |
|     }
 | |
| 
 | |
|     if (reader->state == XML_TEXTREADER_END)
 | |
|         return(0);
 | |
| 
 | |
|     if (reader->node == NULL)
 | |
|         return(xmlTextReaderNextTree(reader));
 | |
| 
 | |
|     if (reader->node->next != NULL) {
 | |
|         reader->node = reader->node->next;
 | |
|         reader->state = XML_TEXTREADER_START;
 | |
|         return(1);
 | |
|     }
 | |
| 
 | |
|     return(0);
 | |
| }
 | |
| 
 | |
| /************************************************************************
 | |
|  *									*
 | |
|  *			Constructor and destructors			*
 | |
|  *									*
 | |
|  ************************************************************************/
 | |
| /**
 | |
|  * xmlNewTextReader:
 | |
|  * @input: the xmlParserInputBufferPtr used to read data
 | |
|  * @URI: the URI information for the source if available
 | |
|  *
 | |
|  * Create an xmlTextReader structure fed with @input
 | |
|  *
 | |
|  * Returns the new xmlTextReaderPtr or NULL in case of error
 | |
|  */
 | |
| xmlTextReaderPtr
 | |
| xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
 | |
|     xmlTextReaderPtr ret;
 | |
| 
 | |
|     if (input == NULL)
 | |
| 	return(NULL);
 | |
|     ret = xmlMalloc(sizeof(xmlTextReader));
 | |
|     if (ret == NULL)
 | |
| 	return(NULL);
 | |
|     memset(ret, 0, sizeof(xmlTextReader));
 | |
|     ret->doc = NULL;
 | |
|     ret->entTab = NULL;
 | |
|     ret->entMax = 0;
 | |
|     ret->entNr = 0;
 | |
|     ret->input = input;
 | |
|     ret->buffer = xmlBufCreate(50);
 | |
|     if (ret->buffer == NULL) {
 | |
|         xmlFree(ret);
 | |
| 	return(NULL);
 | |
|     }
 | |
|     ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
 | |
|     if (ret->sax == NULL) {
 | |
| 	xmlBufFree(ret->buffer);
 | |
| 	xmlFree(ret);
 | |
| 	return(NULL);
 | |
|     }
 | |
|     xmlSAXVersion(ret->sax, 2);
 | |
|     ret->startElement = ret->sax->startElement;
 | |
|     ret->sax->startElement = xmlTextReaderStartElement;
 | |
|     ret->endElement = ret->sax->endElement;
 | |
|     ret->sax->endElement = xmlTextReaderEndElement;
 | |
| #ifdef LIBXML_SAX1_ENABLED
 | |
|     if (ret->sax->initialized == XML_SAX2_MAGIC) {
 | |
| #endif /* LIBXML_SAX1_ENABLED */
 | |
| 	ret->startElementNs = ret->sax->startElementNs;
 | |
| 	ret->sax->startElementNs = xmlTextReaderStartElementNs;
 | |
| 	ret->endElementNs = ret->sax->endElementNs;
 | |
| 	ret->sax->endElementNs = xmlTextReaderEndElementNs;
 | |
| #ifdef LIBXML_SAX1_ENABLED
 | |
|     } else {
 | |
| 	ret->startElementNs = NULL;
 | |
| 	ret->endElementNs = NULL;
 | |
|     }
 | |
| #endif /* LIBXML_SAX1_ENABLED */
 | |
|     ret->characters = ret->sax->characters;
 | |
|     ret->sax->characters = xmlTextReaderCharacters;
 | |
|     ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
 | |
|     ret->cdataBlock = ret->sax->cdataBlock;
 | |
|     ret->sax->cdataBlock = xmlTextReaderCDataBlock;
 | |
| 
 | |
|     ret->mode = XML_TEXTREADER_MODE_INITIAL;
 | |
|     ret->node = NULL;
 | |
|     ret->curnode = NULL;
 | |
|     if (xmlBufUse(ret->input->buffer) < 4) {
 | |
| 	xmlParserInputBufferRead(input, 4);
 | |
|     }
 | |
|     if (xmlBufUse(ret->input->buffer) >= 4) {
 | |
| 	ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
 | |
| 			     (const char *) xmlBufContent(ret->input->buffer),
 | |
|                                             4, URI);
 | |
| 	ret->base = 0;
 | |
| 	ret->cur = 4;
 | |
|     } else {
 | |
| 	ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
 | |
| 	ret->base = 0;
 | |
| 	ret->cur = 0;
 | |
|     }
 | |
| 
 | |
|     if (ret->ctxt == NULL) {
 | |
| 	xmlBufFree(ret->buffer);
 | |
| 	xmlFree(ret->sax);
 | |
| 	xmlFree(ret);
 | |
| 	return(NULL);
 | |
|     }
 | |
|     ret->ctxt->parseMode = XML_PARSE_READER;
 | |
|     ret->ctxt->_private = ret;
 | |
|     ret->ctxt->linenumbers = 1;
 | |
|     ret->ctxt->dictNames = 1;
 | |
|     ret->allocs = XML_TEXTREADER_CTXT;
 | |
|     /*
 | |
|      * use the parser dictionary to allocate all elements and attributes names
 | |
|      */
 | |
|     ret->dict = ret->ctxt->dict;
 | |
| #ifdef LIBXML_XINCLUDE_ENABLED
 | |
|     ret->xinclude = 0;
 | |
| #endif
 | |
| #ifdef LIBXML_PATTERN_ENABLED
 | |
|     ret->patternMax = 0;
 | |
|     ret->patternTab = NULL;
 | |
| #endif
 | |
|     return(ret);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlNewTextReaderFilename:
 | |
|  * @URI: the URI of the resource to process
 | |
|  *
 | |
|  * Create an xmlTextReader structure fed with the resource at @URI
 | |
|  *
 | |
|  * Returns the new xmlTextReaderPtr or NULL in case of error
 | |
|  */
 | |
| xmlTextReaderPtr
 | |
| xmlNewTextReaderFilename(const char *URI) {
 | |
|     xmlParserInputBufferPtr input;
 | |
|     xmlTextReaderPtr ret;
 | |
| 
 | |
|     input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
 | |
|     if (input == NULL)
 | |
| 	return(NULL);
 | |
|     ret = xmlNewTextReader(input, URI);
 | |
|     if (ret == NULL) {
 | |
| 	xmlFreeParserInputBuffer(input);
 | |
| 	return(NULL);
 | |
|     }
 | |
|     ret->allocs |= XML_TEXTREADER_INPUT;
 | |
|     return(ret);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlFreeTextReader:
 | |
|  * @reader:  the xmlTextReaderPtr
 | |
|  *
 | |
|  * Deallocate all the resources associated to the reader
 | |
|  */
 | |
| void
 | |
| xmlFreeTextReader(xmlTextReaderPtr reader) {
 | |
|     if (reader == NULL)
 | |
| 	return;
 | |
| #ifdef LIBXML_SCHEMAS_ENABLED
 | |
|     if (reader->rngSchemas != NULL) {
 | |
| 	xmlRelaxNGFree(reader->rngSchemas);
 | |
| 	reader->rngSchemas = NULL;
 | |
|     }
 | |
|     if (reader->rngValidCtxt != NULL) {
 | |
| 	if (! reader->rngPreserveCtxt)
 | |
| 	    xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
 | |
| 	reader->rngValidCtxt = NULL;
 | |
|     }
 | |
|     if (reader->xsdPlug != NULL) {
 | |
| 	xmlSchemaSAXUnplug(reader->xsdPlug);
 | |
| 	reader->xsdPlug = NULL;
 | |
|     }
 | |
|     if (reader->xsdValidCtxt != NULL) {
 | |
| 	if (! reader->xsdPreserveCtxt)
 | |
| 	    xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
 | |
| 	reader->xsdValidCtxt = NULL;
 | |
|     }
 | |
|     if (reader->xsdSchemas != NULL) {
 | |
| 	xmlSchemaFree(reader->xsdSchemas);
 | |
| 	reader->xsdSchemas = NULL;
 | |
|     }
 | |
| #endif
 | |
| #ifdef LIBXML_XINCLUDE_ENABLED
 | |
|     if (reader->xincctxt != NULL)
 | |
| 	xmlXIncludeFreeContext(reader->xincctxt);
 | |
| #endif
 | |
| #ifdef LIBXML_PATTERN_ENABLED
 | |
|     if (reader->patternTab != NULL) {
 | |
|         int i;
 | |
| 	for (i = 0;i < reader->patternNr;i++) {
 | |
| 	    if (reader->patternTab[i] != NULL)
 | |
| 	        xmlFreePattern(reader->patternTab[i]);
 | |
| 	}
 | |
| 	xmlFree(reader->patternTab);
 | |
|     }
 | |
| #endif
 | |
|     if (reader->mode != XML_TEXTREADER_MODE_CLOSED)
 | |
|         xmlTextReaderClose(reader);
 | |
|     if (reader->ctxt != NULL) {
 | |
|         if (reader->dict == reader->ctxt->dict)
 | |
| 	    reader->dict = NULL;
 | |
| 	if (reader->allocs & XML_TEXTREADER_CTXT)
 | |
| 	    xmlFreeParserCtxt(reader->ctxt);
 | |
|     }
 | |
|     if (reader->sax != NULL)
 | |
| 	xmlFree(reader->sax);
 | |
|     if (reader->buffer != NULL)
 | |
|         xmlBufFree(reader->buffer);
 | |
|     if (reader->entTab != NULL)
 | |
| 	xmlFree(reader->entTab);
 | |
|     if (reader->dict != NULL)
 | |
|         xmlDictFree(reader->dict);
 | |
|     xmlFree(reader);
 | |
| }
 | |
| 
 | |
| /************************************************************************
 | |
|  *									*
 | |
|  *			Methods for XmlTextReader			*
 | |
|  *									*
 | |
|  ************************************************************************/
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderClose:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * This method releases any resources allocated by the current instance
 | |
|  * changes the state to Closed and close any underlying input.
 | |
|  *
 | |
|  * Returns 0 or -1 in case of error
 | |
|  */
 | |
| int
 | |
| xmlTextReaderClose(xmlTextReaderPtr reader) {
 | |
|     if (reader == NULL)
 | |
| 	return(-1);
 | |
|     reader->node = NULL;
 | |
|     reader->curnode = NULL;
 | |
|     reader->mode = XML_TEXTREADER_MODE_CLOSED;
 | |
|     if (reader->faketext != NULL) {
 | |
|         xmlFreeNode(reader->faketext);
 | |
|         reader->faketext = NULL;
 | |
|     }
 | |
|     if (reader->ctxt != NULL) {
 | |
| #ifdef LIBXML_VALID_ENABLED
 | |
| 	if ((reader->ctxt->vctxt.vstateTab != NULL) &&
 | |
| 	    (reader->ctxt->vctxt.vstateMax > 0)){
 | |
| #ifdef LIBXML_REGEXP_ENABLED
 | |
|             while (reader->ctxt->vctxt.vstateNr > 0)
 | |
|                 xmlValidatePopElement(&reader->ctxt->vctxt, NULL, NULL, NULL);
 | |
| #endif /* LIBXML_REGEXP_ENABLED */
 | |
| 	    xmlFree(reader->ctxt->vctxt.vstateTab);
 | |
| 	    reader->ctxt->vctxt.vstateTab = NULL;
 | |
| 	    reader->ctxt->vctxt.vstateMax = 0;
 | |
| 	}
 | |
| #endif /* LIBXML_VALID_ENABLED */
 | |
| 	xmlStopParser(reader->ctxt);
 | |
| 	if (reader->ctxt->myDoc != NULL) {
 | |
| 	    if (reader->preserve == 0)
 | |
| 		xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
 | |
| 	    reader->ctxt->myDoc = NULL;
 | |
| 	}
 | |
|     }
 | |
|     if ((reader->input != NULL)  && (reader->allocs & XML_TEXTREADER_INPUT)) {
 | |
| 	xmlFreeParserInputBuffer(reader->input);
 | |
| 	reader->allocs -= XML_TEXTREADER_INPUT;
 | |
|     }
 | |
|     return(0);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderGetAttributeNo:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @no: the zero-based index of the attribute relative to the containing element
 | |
|  *
 | |
|  * Provides the value of the attribute with the specified index relative
 | |
|  * to the containing element.
 | |
|  *
 | |
|  * Returns a string containing the value of the specified attribute, or NULL
 | |
|  *    in case of error. The string must be deallocated by the caller.
 | |
|  */
 | |
| xmlChar *
 | |
| xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
 | |
|     xmlChar *ret;
 | |
|     int i;
 | |
|     xmlAttrPtr cur;
 | |
|     xmlNsPtr ns;
 | |
| 
 | |
|     if (reader == NULL)
 | |
| 	return(NULL);
 | |
|     if (reader->node == NULL)
 | |
| 	return(NULL);
 | |
|     if (reader->curnode != NULL)
 | |
| 	return(NULL);
 | |
|     /* TODO: handle the xmlDecl */
 | |
|     if (reader->node->type != XML_ELEMENT_NODE)
 | |
| 	return(NULL);
 | |
| 
 | |
|     ns = reader->node->nsDef;
 | |
|     for (i = 0;(i < no) && (ns != NULL);i++) {
 | |
| 	ns = ns->next;
 | |
|     }
 | |
|     if (ns != NULL)
 | |
| 	return(readerStrdup(reader, ns->href));
 | |
| 
 | |
|     cur = reader->node->properties;
 | |
|     if (cur == NULL)
 | |
| 	return(NULL);
 | |
|     for (;i < no;i++) {
 | |
| 	cur = cur->next;
 | |
| 	if (cur == NULL)
 | |
| 	    return(NULL);
 | |
|     }
 | |
|     /* TODO walk the DTD if present */
 | |
| 
 | |
|     ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
 | |
|     if (ret == NULL)
 | |
|         xmlTextReaderErrMemory(reader);
 | |
|     return(ret);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderGetAttribute:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @name: the qualified name of the attribute.
 | |
|  *
 | |
|  * Provides the value of the attribute with the specified qualified name.
 | |
|  *
 | |
|  * Returns a string containing the value of the specified attribute, or NULL
 | |
|  *    in case of error. The string must be deallocated by the caller.
 | |
|  */
 | |
| xmlChar *
 | |
| xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
 | |
|     xmlChar *prefix = NULL;
 | |
|     const xmlChar *localname;
 | |
|     xmlNsPtr ns;
 | |
|     xmlChar *ret = NULL;
 | |
|     int result;
 | |
| 
 | |
|     if ((reader == NULL) || (name == NULL))
 | |
| 	return(NULL);
 | |
|     if (reader->node == NULL)
 | |
| 	return(NULL);
 | |
|     if (reader->curnode != NULL)
 | |
| 	return(NULL);
 | |
| 
 | |
|     /* TODO: handle the xmlDecl */
 | |
|     if (reader->node->type != XML_ELEMENT_NODE)
 | |
| 	return(NULL);
 | |
| 
 | |
|     localname = xmlSplitQName4(name, &prefix);
 | |
|     if (localname == NULL) {
 | |
|         xmlTextReaderErrMemory(reader);
 | |
|         return(NULL);
 | |
|     }
 | |
|     if (prefix == NULL) {
 | |
|         /*
 | |
|          * Namespace default decl
 | |
|          */
 | |
|         if (xmlStrEqual(name, BAD_CAST "xmlns")) {
 | |
|             ns = reader->node->nsDef;
 | |
|             while (ns != NULL) {
 | |
|                 if (ns->prefix == NULL) {
 | |
|                     return(readerStrdup(reader, ns->href));
 | |
|                 }
 | |
|                 ns = ns->next;
 | |
|             }
 | |
|             return NULL;
 | |
|         }
 | |
| 
 | |
|         result = xmlNodeGetAttrValue(reader->node, name, NULL, &ret);
 | |
|         if (result < 0)
 | |
|             xmlTextReaderErrMemory(reader);
 | |
|         return(ret);
 | |
|     }
 | |
| 
 | |
|     /*
 | |
|      * Namespace default decl
 | |
|      */
 | |
|     if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
 | |
|         ns = reader->node->nsDef;
 | |
|         while (ns != NULL) {
 | |
|             if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
 | |
|                 ret = readerStrdup(reader, ns->href);
 | |
|                 break;
 | |
|             }
 | |
|             ns = ns->next;
 | |
|         }
 | |
|     } else {
 | |
|         result = xmlSearchNsSafe(reader->node, prefix, &ns);
 | |
|         if (result < 0)
 | |
|             xmlTextReaderErrMemory(reader);
 | |
|         if (ns != NULL) {
 | |
|             result = xmlNodeGetAttrValue(reader->node, localname, ns->href,
 | |
|                                          &ret);
 | |
|             if (result < 0)
 | |
|                 xmlTextReaderErrMemory(reader);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (prefix != NULL)
 | |
|         xmlFree(prefix);
 | |
|     return(ret);
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderGetAttributeNs:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @localName: the local name of the attribute.
 | |
|  * @namespaceURI: the namespace URI of the attribute.
 | |
|  *
 | |
|  * Provides the value of the specified attribute
 | |
|  *
 | |
|  * Returns a string containing the value of the specified attribute, or NULL
 | |
|  *    in case of error. The string must be deallocated by the caller.
 | |
|  */
 | |
| xmlChar *
 | |
| xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
 | |
| 			    const xmlChar *namespaceURI) {
 | |
|     xmlChar *ret = NULL;
 | |
|     xmlChar *prefix = NULL;
 | |
|     xmlNsPtr ns;
 | |
|     int result;
 | |
| 
 | |
|     if ((reader == NULL) || (localName == NULL))
 | |
| 	return(NULL);
 | |
|     if (reader->node == NULL)
 | |
| 	return(NULL);
 | |
|     if (reader->curnode != NULL)
 | |
| 	return(NULL);
 | |
| 
 | |
|     /* TODO: handle the xmlDecl */
 | |
|     if (reader->node->type != XML_ELEMENT_NODE)
 | |
| 	return(NULL);
 | |
| 
 | |
|     if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
 | |
|         if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
 | |
|             prefix = BAD_CAST localName;
 | |
|         }
 | |
|         ns = reader->node->nsDef;
 | |
|         while (ns != NULL) {
 | |
|             if ((prefix == NULL && ns->prefix == NULL) ||
 | |
|                 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
 | |
|                 return readerStrdup(reader, ns->href);
 | |
|             }
 | |
|             ns = ns->next;
 | |
|         }
 | |
|         return NULL;
 | |
|     }
 | |
| 
 | |
|     result = xmlNodeGetAttrValue(reader->node, localName, namespaceURI, &ret);
 | |
|     if (result < 0)
 | |
|         xmlTextReaderErrMemory(reader);
 | |
| 
 | |
|     return(ret);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderGetRemainder:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Method to get the remainder of the buffered XML. this method stops the
 | |
|  * parser, set its state to End Of File and return the input stream with
 | |
|  * what is left that the parser did not use.
 | |
|  *
 | |
|  * The implementation is not good, the parser certainly progressed past
 | |
|  * what's left in reader->input, and there is an allocation problem. Best
 | |
|  * would be to rewrite it differently.
 | |
|  *
 | |
|  * Returns the xmlParserInputBufferPtr attached to the XML or NULL
 | |
|  *    in case of error.
 | |
|  */
 | |
| xmlParserInputBufferPtr
 | |
| xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
 | |
|     xmlParserInputBufferPtr ret = NULL;
 | |
| 
 | |
|     if (reader == NULL)
 | |
| 	return(NULL);
 | |
|     if (reader->node == NULL)
 | |
| 	return(NULL);
 | |
| 
 | |
|     reader->node = NULL;
 | |
|     reader->curnode = NULL;
 | |
|     reader->mode = XML_TEXTREADER_MODE_EOF;
 | |
|     if (reader->ctxt != NULL) {
 | |
| 	xmlStopParser(reader->ctxt);
 | |
| 	if (reader->ctxt->myDoc != NULL) {
 | |
| 	    if (reader->preserve == 0)
 | |
| 		xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
 | |
| 	    reader->ctxt->myDoc = NULL;
 | |
| 	}
 | |
|     }
 | |
|     if (reader->allocs & XML_TEXTREADER_INPUT) {
 | |
| 	ret = reader->input;
 | |
| 	reader->input = NULL;
 | |
| 	reader->allocs -= XML_TEXTREADER_INPUT;
 | |
|     } else {
 | |
| 	/*
 | |
| 	 * Hum, one may need to duplicate the data structure because
 | |
| 	 * without reference counting the input may be freed twice:
 | |
| 	 *   - by the layer which allocated it.
 | |
| 	 *   - by the layer to which would have been returned to.
 | |
| 	 */
 | |
| 	return(NULL);
 | |
|     }
 | |
|     return(ret);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderLookupNamespace:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @prefix: the prefix whose namespace URI is to be resolved. To return
 | |
|  *          the default namespace, specify NULL
 | |
|  *
 | |
|  * Resolves a namespace prefix in the scope of the current element.
 | |
|  *
 | |
|  * Returns a string containing the namespace URI to which the prefix maps
 | |
|  *    or NULL in case of error. The string must be deallocated by the caller.
 | |
|  */
 | |
| xmlChar *
 | |
| xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
 | |
|     xmlNsPtr ns;
 | |
|     int result;
 | |
| 
 | |
|     if (reader == NULL)
 | |
| 	return(NULL);
 | |
|     if (reader->node == NULL)
 | |
| 	return(NULL);
 | |
| 
 | |
|     result = xmlSearchNsSafe(reader->node, prefix, &ns);
 | |
|     if (result < 0) {
 | |
|         xmlTextReaderErrMemory(reader);
 | |
|         return(NULL);
 | |
|     }
 | |
|     if (ns == NULL)
 | |
| 	return(NULL);
 | |
|     return(readerStrdup(reader, ns->href));
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderMoveToAttributeNo:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @no: the zero-based index of the attribute relative to the containing
 | |
|  *      element.
 | |
|  *
 | |
|  * Moves the position of the current instance to the attribute with
 | |
|  * the specified index relative to the containing element.
 | |
|  *
 | |
|  * Returns 1 in case of success, -1 in case of error, 0 if not found
 | |
|  */
 | |
| int
 | |
| xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
 | |
|     int i;
 | |
|     xmlAttrPtr cur;
 | |
|     xmlNsPtr ns;
 | |
| 
 | |
|     if (reader == NULL)
 | |
| 	return(-1);
 | |
|     if (reader->node == NULL)
 | |
| 	return(-1);
 | |
|     /* TODO: handle the xmlDecl */
 | |
|     if (reader->node->type != XML_ELEMENT_NODE)
 | |
| 	return(-1);
 | |
| 
 | |
|     reader->curnode = NULL;
 | |
| 
 | |
|     ns = reader->node->nsDef;
 | |
|     for (i = 0;(i < no) && (ns != NULL);i++) {
 | |
| 	ns = ns->next;
 | |
|     }
 | |
|     if (ns != NULL) {
 | |
| 	reader->curnode = (xmlNodePtr) ns;
 | |
| 	return(1);
 | |
|     }
 | |
| 
 | |
|     cur = reader->node->properties;
 | |
|     if (cur == NULL)
 | |
| 	return(0);
 | |
|     for (;i < no;i++) {
 | |
| 	cur = cur->next;
 | |
| 	if (cur == NULL)
 | |
| 	    return(0);
 | |
|     }
 | |
|     /* TODO walk the DTD if present */
 | |
| 
 | |
|     reader->curnode = (xmlNodePtr) cur;
 | |
|     return(1);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderMoveToAttribute:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @name: the qualified name of the attribute.
 | |
|  *
 | |
|  * Moves the position of the current instance to the attribute with
 | |
|  * the specified qualified name.
 | |
|  *
 | |
|  * Returns 1 in case of success, -1 in case of error, 0 if not found
 | |
|  */
 | |
| int
 | |
| xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
 | |
|     xmlChar *prefix = NULL;
 | |
|     const xmlChar *localname;
 | |
|     xmlNsPtr ns;
 | |
|     xmlAttrPtr prop;
 | |
| 
 | |
|     if ((reader == NULL) || (name == NULL))
 | |
| 	return(-1);
 | |
|     if (reader->node == NULL)
 | |
| 	return(-1);
 | |
| 
 | |
|     /* TODO: handle the xmlDecl */
 | |
|     if (reader->node->type != XML_ELEMENT_NODE)
 | |
| 	return(0);
 | |
| 
 | |
|     localname = xmlSplitQName4(name, &prefix);
 | |
|     if (localname == NULL) {
 | |
|         xmlTextReaderErrMemory(reader);
 | |
|         return(-1);
 | |
|     }
 | |
|     if (prefix == NULL) {
 | |
| 	/*
 | |
| 	 * Namespace default decl
 | |
| 	 */
 | |
| 	if (xmlStrEqual(name, BAD_CAST "xmlns")) {
 | |
| 	    ns = reader->node->nsDef;
 | |
| 	    while (ns != NULL) {
 | |
| 		if (ns->prefix == NULL) {
 | |
| 		    reader->curnode = (xmlNodePtr) ns;
 | |
| 		    return(1);
 | |
| 		}
 | |
| 		ns = ns->next;
 | |
| 	    }
 | |
| 	    return(0);
 | |
| 	}
 | |
| 
 | |
| 	prop = reader->node->properties;
 | |
| 	while (prop != NULL) {
 | |
| 	    /*
 | |
| 	     * One need to have
 | |
| 	     *   - same attribute names
 | |
| 	     *   - and the attribute carrying that namespace
 | |
| 	     */
 | |
| 	    if ((xmlStrEqual(prop->name, name)) &&
 | |
| 		((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
 | |
| 		reader->curnode = (xmlNodePtr) prop;
 | |
| 		return(1);
 | |
| 	    }
 | |
| 	    prop = prop->next;
 | |
| 	}
 | |
| 	return(0);
 | |
|     }
 | |
| 
 | |
|     /*
 | |
|      * Namespace default decl
 | |
|      */
 | |
|     if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
 | |
| 	ns = reader->node->nsDef;
 | |
| 	while (ns != NULL) {
 | |
| 	    if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
 | |
| 		reader->curnode = (xmlNodePtr) ns;
 | |
| 		goto found;
 | |
| 	    }
 | |
| 	    ns = ns->next;
 | |
| 	}
 | |
| 	goto not_found;
 | |
|     }
 | |
|     prop = reader->node->properties;
 | |
|     while (prop != NULL) {
 | |
| 	/*
 | |
| 	 * One need to have
 | |
| 	 *   - same attribute names
 | |
| 	 *   - and the attribute carrying that namespace
 | |
| 	 */
 | |
| 	if ((xmlStrEqual(prop->name, localname)) &&
 | |
| 	    (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
 | |
| 	    reader->curnode = (xmlNodePtr) prop;
 | |
| 	    goto found;
 | |
| 	}
 | |
| 	prop = prop->next;
 | |
|     }
 | |
| not_found:
 | |
|     if (prefix != NULL)
 | |
|         xmlFree(prefix);
 | |
|     return(0);
 | |
| 
 | |
| found:
 | |
|     if (prefix != NULL)
 | |
|         xmlFree(prefix);
 | |
|     return(1);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderMoveToAttributeNs:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @localName:  the local name of the attribute.
 | |
|  * @namespaceURI:  the namespace URI of the attribute.
 | |
|  *
 | |
|  * Moves the position of the current instance to the attribute with the
 | |
|  * specified local name and namespace URI.
 | |
|  *
 | |
|  * Returns 1 in case of success, -1 in case of error, 0 if not found
 | |
|  */
 | |
| int
 | |
| xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
 | |
| 	const xmlChar *localName, const xmlChar *namespaceURI) {
 | |
|     xmlAttrPtr prop;
 | |
|     xmlNodePtr node;
 | |
|     xmlNsPtr ns;
 | |
|     xmlChar *prefix = NULL;
 | |
| 
 | |
|     if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
 | |
| 	return(-1);
 | |
|     if (reader->node == NULL)
 | |
| 	return(-1);
 | |
|     if (reader->node->type != XML_ELEMENT_NODE)
 | |
| 	return(0);
 | |
|     node = reader->node;
 | |
| 
 | |
|     if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
 | |
| 		if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
 | |
| 			prefix = BAD_CAST localName;
 | |
| 		}
 | |
| 		ns = reader->node->nsDef;
 | |
| 		while (ns != NULL) {
 | |
| 			if ((prefix == NULL && ns->prefix == NULL) ||
 | |
| 				((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
 | |
| 				reader->curnode = (xmlNodePtr) ns;
 | |
| 				return(1);
 | |
| 			}
 | |
| 			ns = ns->next;
 | |
| 		}
 | |
| 		return(0);
 | |
|     }
 | |
| 
 | |
|     prop = node->properties;
 | |
|     while (prop != NULL) {
 | |
| 	/*
 | |
| 	 * One need to have
 | |
| 	 *   - same attribute names
 | |
| 	 *   - and the attribute carrying that namespace
 | |
| 	 */
 | |
|         if (xmlStrEqual(prop->name, localName) &&
 | |
| 	    ((prop->ns != NULL) &&
 | |
| 	     (xmlStrEqual(prop->ns->href, namespaceURI)))) {
 | |
| 	    reader->curnode = (xmlNodePtr) prop;
 | |
| 	    return(1);
 | |
|         }
 | |
| 	prop = prop->next;
 | |
|     }
 | |
|     return(0);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderMoveToFirstAttribute:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Moves the position of the current instance to the first attribute
 | |
|  * associated with the current node.
 | |
|  *
 | |
|  * Returns 1 in case of success, -1 in case of error, 0 if not found
 | |
|  */
 | |
| int
 | |
| xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
 | |
|     if (reader == NULL)
 | |
| 	return(-1);
 | |
|     if (reader->node == NULL)
 | |
| 	return(-1);
 | |
|     if (reader->node->type != XML_ELEMENT_NODE)
 | |
| 	return(0);
 | |
| 
 | |
|     if (reader->node->nsDef != NULL) {
 | |
| 	reader->curnode = (xmlNodePtr) reader->node->nsDef;
 | |
| 	return(1);
 | |
|     }
 | |
|     if (reader->node->properties != NULL) {
 | |
| 	reader->curnode = (xmlNodePtr) reader->node->properties;
 | |
| 	return(1);
 | |
|     }
 | |
|     return(0);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderMoveToNextAttribute:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Moves the position of the current instance to the next attribute
 | |
|  * associated with the current node.
 | |
|  *
 | |
|  * Returns 1 in case of success, -1 in case of error, 0 if not found
 | |
|  */
 | |
| int
 | |
| xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
 | |
|     if (reader == NULL)
 | |
| 	return(-1);
 | |
|     if (reader->node == NULL)
 | |
| 	return(-1);
 | |
|     if (reader->node->type != XML_ELEMENT_NODE)
 | |
| 	return(0);
 | |
|     if (reader->curnode == NULL)
 | |
| 	return(xmlTextReaderMoveToFirstAttribute(reader));
 | |
| 
 | |
|     if (reader->curnode->type == XML_NAMESPACE_DECL) {
 | |
| 	xmlNsPtr ns = (xmlNsPtr) reader->curnode;
 | |
| 	if (ns->next != NULL) {
 | |
| 	    reader->curnode = (xmlNodePtr) ns->next;
 | |
| 	    return(1);
 | |
| 	}
 | |
| 	if (reader->node->properties != NULL) {
 | |
| 	    reader->curnode = (xmlNodePtr) reader->node->properties;
 | |
| 	    return(1);
 | |
| 	}
 | |
| 	return(0);
 | |
|     } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
 | |
| 	       (reader->curnode->next != NULL)) {
 | |
| 	reader->curnode = reader->curnode->next;
 | |
| 	return(1);
 | |
|     }
 | |
|     return(0);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderMoveToElement:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Moves the position of the current instance to the node that
 | |
|  * contains the current Attribute  node.
 | |
|  *
 | |
|  * Returns 1 in case of success, -1 in case of error, 0 if not moved
 | |
|  */
 | |
| int
 | |
| xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
 | |
|     if (reader == NULL)
 | |
| 	return(-1);
 | |
|     if (reader->node == NULL)
 | |
| 	return(-1);
 | |
|     if (reader->node->type != XML_ELEMENT_NODE)
 | |
| 	return(0);
 | |
|     if (reader->curnode != NULL) {
 | |
| 	reader->curnode = NULL;
 | |
| 	return(1);
 | |
|     }
 | |
|     return(0);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderReadAttributeValue:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Parses an attribute value into one or more Text and EntityReference nodes.
 | |
|  *
 | |
|  * Returns 1 in case of success, 0 if the reader was not positioned on an
 | |
|  *         attribute node or all the attribute values have been read, or -1
 | |
|  *         in case of error.
 | |
|  */
 | |
| int
 | |
| xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
 | |
|     if (reader == NULL)
 | |
| 	return(-1);
 | |
|     if (reader->node == NULL)
 | |
| 	return(-1);
 | |
|     if (reader->curnode == NULL)
 | |
| 	return(0);
 | |
|     if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
 | |
| 	if (reader->curnode->children == NULL)
 | |
| 	    return(0);
 | |
| 	reader->curnode = reader->curnode->children;
 | |
|     } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
 | |
| 	xmlNsPtr ns = (xmlNsPtr) reader->curnode;
 | |
| 
 | |
| 	if (reader->faketext == NULL) {
 | |
| 	    reader->faketext = xmlNewDocText(reader->node->doc,
 | |
| 		                             ns->href);
 | |
|             if (reader->faketext == NULL) {
 | |
|                 xmlTextReaderErrMemory(reader);
 | |
|                 return(-1);
 | |
|             }
 | |
| 	} else {
 | |
|             if ((reader->faketext->content != NULL) &&
 | |
| 	        (reader->faketext->content !=
 | |
| 		 (xmlChar *) &(reader->faketext->properties)))
 | |
| 		xmlFree(reader->faketext->content);
 | |
|             if (ns->href == NULL) {
 | |
|                 reader->faketext->content = NULL;
 | |
|             } else {
 | |
|                 reader->faketext->content = xmlStrdup(ns->href);
 | |
|                 if (reader->faketext->content == NULL) {
 | |
|                     xmlTextReaderErrMemory(reader);
 | |
|                     return(-1);
 | |
|                 }
 | |
|             }
 | |
| 	}
 | |
| 	reader->curnode = reader->faketext;
 | |
|     } else {
 | |
| 	if (reader->curnode->next == NULL)
 | |
| 	    return(0);
 | |
| 	reader->curnode = reader->curnode->next;
 | |
|     }
 | |
|     return(1);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderConstEncoding:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Determine the encoding of the document being read.
 | |
|  *
 | |
|  * Returns a string containing the encoding of the document or NULL in
 | |
|  * case of error.  The string is deallocated with the reader.
 | |
|  */
 | |
| const xmlChar *
 | |
| xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
 | |
|     const xmlChar *encoding = NULL;
 | |
| 
 | |
|     if (reader == NULL)
 | |
|         return(NULL);
 | |
| 
 | |
|     if (reader->ctxt != NULL)
 | |
|         encoding = xmlGetActualEncoding(reader->ctxt);
 | |
|     else if (reader->doc != NULL)
 | |
|         encoding = reader->doc->encoding;
 | |
| 
 | |
|     return(constString(reader, encoding));
 | |
| }
 | |
| 
 | |
| 
 | |
| /************************************************************************
 | |
|  *									*
 | |
|  *			Access API to the current node			*
 | |
|  *									*
 | |
|  ************************************************************************/
 | |
| /**
 | |
|  * xmlTextReaderAttributeCount:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Provides the number of attributes of the current node
 | |
|  *
 | |
|  * Returns 0 i no attributes, -1 in case of error or the attribute count
 | |
|  */
 | |
| int
 | |
| xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
 | |
|     int ret;
 | |
|     xmlAttrPtr attr;
 | |
|     xmlNsPtr ns;
 | |
|     xmlNodePtr node;
 | |
| 
 | |
|     if (reader == NULL)
 | |
| 	return(-1);
 | |
|     if (reader->node == NULL)
 | |
| 	return(0);
 | |
| 
 | |
|     if (reader->curnode != NULL)
 | |
| 	node = reader->curnode;
 | |
|     else
 | |
| 	node = reader->node;
 | |
| 
 | |
|     if (node->type != XML_ELEMENT_NODE)
 | |
| 	return(0);
 | |
|     if ((reader->state == XML_TEXTREADER_END) ||
 | |
| 	(reader->state == XML_TEXTREADER_BACKTRACK))
 | |
| 	return(0);
 | |
|     ret = 0;
 | |
|     attr = node->properties;
 | |
|     while (attr != NULL) {
 | |
| 	ret++;
 | |
| 	attr = attr->next;
 | |
|     }
 | |
|     ns = node->nsDef;
 | |
|     while (ns != NULL) {
 | |
| 	ret++;
 | |
| 	ns = ns->next;
 | |
|     }
 | |
|     return(ret);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderNodeType:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Get the node type of the current node
 | |
|  * Reference:
 | |
|  * http://www.gnu.org/software/dotgnu/pnetlib-doc/System/Xml/XmlNodeType.html
 | |
|  *
 | |
|  * Returns the xmlReaderTypes of the current node or -1 in case of error
 | |
|  */
 | |
| int
 | |
| xmlTextReaderNodeType(xmlTextReaderPtr reader) {
 | |
|     xmlNodePtr node;
 | |
| 
 | |
|     if (reader == NULL)
 | |
| 	return(-1);
 | |
|     if (reader->node == NULL)
 | |
| 	return(XML_READER_TYPE_NONE);
 | |
|     if (reader->curnode != NULL)
 | |
| 	node = reader->curnode;
 | |
|     else
 | |
| 	node = reader->node;
 | |
|     switch (node->type) {
 | |
|         case XML_ELEMENT_NODE:
 | |
| 	    if ((reader->state == XML_TEXTREADER_END) ||
 | |
| 		(reader->state == XML_TEXTREADER_BACKTRACK))
 | |
| 		return(XML_READER_TYPE_END_ELEMENT);
 | |
| 	    return(XML_READER_TYPE_ELEMENT);
 | |
|         case XML_NAMESPACE_DECL:
 | |
|         case XML_ATTRIBUTE_NODE:
 | |
| 	    return(XML_READER_TYPE_ATTRIBUTE);
 | |
|         case XML_TEXT_NODE:
 | |
| 	    if (xmlIsBlankNode(reader->node)) {
 | |
| 		if (xmlNodeGetSpacePreserve(reader->node))
 | |
| 		    return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
 | |
| 		else
 | |
| 		    return(XML_READER_TYPE_WHITESPACE);
 | |
| 	    } else {
 | |
| 		return(XML_READER_TYPE_TEXT);
 | |
| 	    }
 | |
|         case XML_CDATA_SECTION_NODE:
 | |
| 	    return(XML_READER_TYPE_CDATA);
 | |
|         case XML_ENTITY_REF_NODE:
 | |
| 	    return(XML_READER_TYPE_ENTITY_REFERENCE);
 | |
|         case XML_ENTITY_NODE:
 | |
| 	    return(XML_READER_TYPE_ENTITY);
 | |
|         case XML_PI_NODE:
 | |
| 	    return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
 | |
|         case XML_COMMENT_NODE:
 | |
| 	    return(XML_READER_TYPE_COMMENT);
 | |
|         case XML_DOCUMENT_NODE:
 | |
|         case XML_HTML_DOCUMENT_NODE:
 | |
| 	    return(XML_READER_TYPE_DOCUMENT);
 | |
|         case XML_DOCUMENT_FRAG_NODE:
 | |
| 	    return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
 | |
|         case XML_NOTATION_NODE:
 | |
| 	    return(XML_READER_TYPE_NOTATION);
 | |
|         case XML_DOCUMENT_TYPE_NODE:
 | |
|         case XML_DTD_NODE:
 | |
| 	    return(XML_READER_TYPE_DOCUMENT_TYPE);
 | |
| 
 | |
|         case XML_ELEMENT_DECL:
 | |
|         case XML_ATTRIBUTE_DECL:
 | |
|         case XML_ENTITY_DECL:
 | |
|         case XML_XINCLUDE_START:
 | |
|         case XML_XINCLUDE_END:
 | |
| 	    return(XML_READER_TYPE_NONE);
 | |
|     }
 | |
|     return(-1);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderIsEmptyElement:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Check if the current node is empty
 | |
|  *
 | |
|  * Returns 1 if empty, 0 if not and -1 in case of error
 | |
|  */
 | |
| int
 | |
| xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
 | |
|     if ((reader == NULL) || (reader->node == NULL))
 | |
| 	return(-1);
 | |
|     if (reader->node->type != XML_ELEMENT_NODE)
 | |
| 	return(0);
 | |
|     if (reader->curnode != NULL)
 | |
| 	return(0);
 | |
|     if (reader->node->children != NULL)
 | |
| 	return(0);
 | |
|     if (reader->state == XML_TEXTREADER_END)
 | |
| 	return(0);
 | |
|     if (reader->doc != NULL)
 | |
|         return(1);
 | |
| #ifdef LIBXML_XINCLUDE_ENABLED
 | |
|     if (reader->in_xinclude > 0)
 | |
|         return(1);
 | |
| #endif
 | |
|     return((reader->node->extra & NODE_IS_EMPTY) != 0);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderLocalName:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * The local name of the node.
 | |
|  *
 | |
|  * Returns the local name or NULL if not available,
 | |
|  *   if non NULL it need to be freed by the caller.
 | |
|  */
 | |
| xmlChar *
 | |
| xmlTextReaderLocalName(xmlTextReaderPtr reader) {
 | |
|     xmlNodePtr node;
 | |
|     if ((reader == NULL) || (reader->node == NULL))
 | |
| 	return(NULL);
 | |
|     if (reader->curnode != NULL)
 | |
| 	node = reader->curnode;
 | |
|     else
 | |
| 	node = reader->node;
 | |
|     if (node->type == XML_NAMESPACE_DECL) {
 | |
| 	xmlNsPtr ns = (xmlNsPtr) node;
 | |
| 	if (ns->prefix == NULL)
 | |
| 	    return(readerStrdup(reader, BAD_CAST "xmlns"));
 | |
| 	else
 | |
| 	    return(readerStrdup(reader, ns->prefix));
 | |
|     }
 | |
|     if ((node->type != XML_ELEMENT_NODE) &&
 | |
| 	(node->type != XML_ATTRIBUTE_NODE))
 | |
| 	return(xmlTextReaderName(reader));
 | |
|     return(readerStrdup(reader, node->name));
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderConstLocalName:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * The local name of the node.
 | |
|  *
 | |
|  * Returns the local name or NULL if not available, the
 | |
|  *         string will be deallocated with the reader.
 | |
|  */
 | |
| const xmlChar *
 | |
| xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
 | |
|     xmlNodePtr node;
 | |
|     if ((reader == NULL) || (reader->node == NULL))
 | |
| 	return(NULL);
 | |
|     if (reader->curnode != NULL)
 | |
| 	node = reader->curnode;
 | |
|     else
 | |
| 	node = reader->node;
 | |
|     if (node->type == XML_NAMESPACE_DECL) {
 | |
| 	xmlNsPtr ns = (xmlNsPtr) node;
 | |
| 	if (ns->prefix == NULL)
 | |
| 	    return(constString(reader, BAD_CAST "xmlns"));
 | |
| 	else
 | |
| 	    return(ns->prefix);
 | |
|     }
 | |
|     if ((node->type != XML_ELEMENT_NODE) &&
 | |
| 	(node->type != XML_ATTRIBUTE_NODE))
 | |
| 	return(xmlTextReaderConstName(reader));
 | |
|     return(node->name);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderName:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * The qualified name of the node, equal to Prefix :LocalName.
 | |
|  *
 | |
|  * Returns the local name or NULL if not available,
 | |
|  *   if non NULL it need to be freed by the caller.
 | |
|  */
 | |
| xmlChar *
 | |
| xmlTextReaderName(xmlTextReaderPtr reader) {
 | |
|     xmlNodePtr node;
 | |
|     xmlChar *ret;
 | |
| 
 | |
|     if ((reader == NULL) || (reader->node == NULL))
 | |
| 	return(NULL);
 | |
|     if (reader->curnode != NULL)
 | |
| 	node = reader->curnode;
 | |
|     else
 | |
| 	node = reader->node;
 | |
|     switch (node->type) {
 | |
|         case XML_ELEMENT_NODE:
 | |
|         case XML_ATTRIBUTE_NODE:
 | |
| 	    if ((node->ns == NULL) ||
 | |
| 		(node->ns->prefix == NULL))
 | |
| 		return(readerStrdup(reader, node->name));
 | |
| 
 | |
|             ret = xmlBuildQName(node->name, node->ns->prefix, NULL, 0);
 | |
|             if (ret == NULL)
 | |
|                 xmlTextReaderErrMemory(reader);
 | |
| 	    return(ret);
 | |
|         case XML_TEXT_NODE:
 | |
| 	    return(readerStrdup(reader, BAD_CAST "#text"));
 | |
|         case XML_CDATA_SECTION_NODE:
 | |
| 	    return(readerStrdup(reader, BAD_CAST "#cdata-section"));
 | |
|         case XML_ENTITY_NODE:
 | |
|         case XML_ENTITY_REF_NODE:
 | |
| 	    return(readerStrdup(reader, node->name));
 | |
|         case XML_PI_NODE:
 | |
| 	    return(readerStrdup(reader, node->name));
 | |
|         case XML_COMMENT_NODE:
 | |
| 	    return(readerStrdup(reader, BAD_CAST "#comment"));
 | |
|         case XML_DOCUMENT_NODE:
 | |
|         case XML_HTML_DOCUMENT_NODE:
 | |
| 	    return(readerStrdup(reader, BAD_CAST "#document"));
 | |
|         case XML_DOCUMENT_FRAG_NODE:
 | |
| 	    return(readerStrdup(reader, BAD_CAST "#document-fragment"));
 | |
|         case XML_NOTATION_NODE:
 | |
| 	    return(readerStrdup(reader, node->name));
 | |
|         case XML_DOCUMENT_TYPE_NODE:
 | |
|         case XML_DTD_NODE:
 | |
| 	    return(readerStrdup(reader, node->name));
 | |
|         case XML_NAMESPACE_DECL: {
 | |
| 	    xmlNsPtr ns = (xmlNsPtr) node;
 | |
| 
 | |
| 	    if (ns->prefix == NULL)
 | |
| 		return(readerStrdup(reader, BAD_CAST "xmlns"));
 | |
|             ret = xmlBuildQName(ns->prefix, BAD_CAST "xmlns", NULL, 0);
 | |
|             if (ret == NULL)
 | |
|                 xmlTextReaderErrMemory(reader);
 | |
| 	    return(ret);
 | |
| 	}
 | |
| 
 | |
|         case XML_ELEMENT_DECL:
 | |
|         case XML_ATTRIBUTE_DECL:
 | |
|         case XML_ENTITY_DECL:
 | |
|         case XML_XINCLUDE_START:
 | |
|         case XML_XINCLUDE_END:
 | |
| 	    return(NULL);
 | |
|     }
 | |
|     return(NULL);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderConstName:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * The qualified name of the node, equal to Prefix :LocalName.
 | |
|  *
 | |
|  * Returns the local name or NULL if not available, the string is
 | |
|  *         deallocated with the reader.
 | |
|  */
 | |
| const xmlChar *
 | |
| xmlTextReaderConstName(xmlTextReaderPtr reader) {
 | |
|     xmlNodePtr node;
 | |
| 
 | |
|     if ((reader == NULL) || (reader->node == NULL))
 | |
| 	return(NULL);
 | |
|     if (reader->curnode != NULL)
 | |
| 	node = reader->curnode;
 | |
|     else
 | |
| 	node = reader->node;
 | |
|     switch (node->type) {
 | |
|         case XML_ELEMENT_NODE:
 | |
|         case XML_ATTRIBUTE_NODE:
 | |
| 	    if ((node->ns == NULL) ||
 | |
| 		(node->ns->prefix == NULL))
 | |
| 		return(node->name);
 | |
| 	    return(constQString(reader, node->ns->prefix, node->name));
 | |
|         case XML_TEXT_NODE:
 | |
| 	    return(constString(reader, BAD_CAST "#text"));
 | |
|         case XML_CDATA_SECTION_NODE:
 | |
| 	    return(constString(reader, BAD_CAST "#cdata-section"));
 | |
|         case XML_ENTITY_NODE:
 | |
|         case XML_ENTITY_REF_NODE:
 | |
| 	    return(constString(reader, node->name));
 | |
|         case XML_PI_NODE:
 | |
| 	    return(constString(reader, node->name));
 | |
|         case XML_COMMENT_NODE:
 | |
| 	    return(constString(reader, BAD_CAST "#comment"));
 | |
|         case XML_DOCUMENT_NODE:
 | |
|         case XML_HTML_DOCUMENT_NODE:
 | |
| 	    return(constString(reader, BAD_CAST "#document"));
 | |
|         case XML_DOCUMENT_FRAG_NODE:
 | |
| 	    return(constString(reader, BAD_CAST "#document-fragment"));
 | |
|         case XML_NOTATION_NODE:
 | |
| 	    return(constString(reader, node->name));
 | |
|         case XML_DOCUMENT_TYPE_NODE:
 | |
|         case XML_DTD_NODE:
 | |
| 	    return(constString(reader, node->name));
 | |
|         case XML_NAMESPACE_DECL: {
 | |
| 	    xmlNsPtr ns = (xmlNsPtr) node;
 | |
| 
 | |
| 	    if (ns->prefix == NULL)
 | |
| 		return(constString(reader, BAD_CAST "xmlns"));
 | |
| 	    return(constQString(reader, BAD_CAST "xmlns", ns->prefix));
 | |
| 	}
 | |
| 
 | |
|         case XML_ELEMENT_DECL:
 | |
|         case XML_ATTRIBUTE_DECL:
 | |
|         case XML_ENTITY_DECL:
 | |
|         case XML_XINCLUDE_START:
 | |
|         case XML_XINCLUDE_END:
 | |
| 	    return(NULL);
 | |
|     }
 | |
|     return(NULL);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderPrefix:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * A shorthand reference to the namespace associated with the node.
 | |
|  *
 | |
|  * Returns the prefix or NULL if not available,
 | |
|  *    if non NULL it need to be freed by the caller.
 | |
|  */
 | |
| xmlChar *
 | |
| xmlTextReaderPrefix(xmlTextReaderPtr reader) {
 | |
|     xmlNodePtr node;
 | |
|     if ((reader == NULL) || (reader->node == NULL))
 | |
| 	return(NULL);
 | |
|     if (reader->curnode != NULL)
 | |
| 	node = reader->curnode;
 | |
|     else
 | |
| 	node = reader->node;
 | |
|     if (node->type == XML_NAMESPACE_DECL) {
 | |
| 	xmlNsPtr ns = (xmlNsPtr) node;
 | |
| 	if (ns->prefix == NULL)
 | |
| 	    return(NULL);
 | |
| 	return(readerStrdup(reader, BAD_CAST "xmlns"));
 | |
|     }
 | |
|     if ((node->type != XML_ELEMENT_NODE) &&
 | |
| 	(node->type != XML_ATTRIBUTE_NODE))
 | |
| 	return(NULL);
 | |
|     if ((node->ns != NULL) && (node->ns->prefix != NULL))
 | |
| 	return(readerStrdup(reader, node->ns->prefix));
 | |
|     return(NULL);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderConstPrefix:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * A shorthand reference to the namespace associated with the node.
 | |
|  *
 | |
|  * Returns the prefix or NULL if not available, the string is deallocated
 | |
|  *         with the reader.
 | |
|  */
 | |
| const xmlChar *
 | |
| xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
 | |
|     xmlNodePtr node;
 | |
|     if ((reader == NULL) || (reader->node == NULL))
 | |
| 	return(NULL);
 | |
|     if (reader->curnode != NULL)
 | |
| 	node = reader->curnode;
 | |
|     else
 | |
| 	node = reader->node;
 | |
|     if (node->type == XML_NAMESPACE_DECL) {
 | |
| 	xmlNsPtr ns = (xmlNsPtr) node;
 | |
| 	if (ns->prefix == NULL)
 | |
| 	    return(NULL);
 | |
| 	return(constString(reader, BAD_CAST "xmlns"));
 | |
|     }
 | |
|     if ((node->type != XML_ELEMENT_NODE) &&
 | |
| 	(node->type != XML_ATTRIBUTE_NODE))
 | |
| 	return(NULL);
 | |
|     if ((node->ns != NULL) && (node->ns->prefix != NULL))
 | |
| 	return(constString(reader, node->ns->prefix));
 | |
|     return(NULL);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderNamespaceUri:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * The URI defining the namespace associated with the node.
 | |
|  *
 | |
|  * Returns the namespace URI or NULL if not available,
 | |
|  *    if non NULL it need to be freed by the caller.
 | |
|  */
 | |
| xmlChar *
 | |
| xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
 | |
|     xmlNodePtr node;
 | |
|     if ((reader == NULL) || (reader->node == NULL))
 | |
| 	return(NULL);
 | |
|     if (reader->curnode != NULL)
 | |
| 	node = reader->curnode;
 | |
|     else
 | |
| 	node = reader->node;
 | |
|     if (node->type == XML_NAMESPACE_DECL)
 | |
| 	return(readerStrdup(reader, BAD_CAST "http://www.w3.org/2000/xmlns/"));
 | |
|     if ((node->type != XML_ELEMENT_NODE) &&
 | |
| 	(node->type != XML_ATTRIBUTE_NODE))
 | |
| 	return(NULL);
 | |
|     if (node->ns != NULL)
 | |
| 	return(readerStrdup(reader, node->ns->href));
 | |
|     return(NULL);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderConstNamespaceUri:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * The URI defining the namespace associated with the node.
 | |
|  *
 | |
|  * Returns the namespace URI or NULL if not available, the string
 | |
|  *         will be deallocated with the reader
 | |
|  */
 | |
| const xmlChar *
 | |
| xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
 | |
|     xmlNodePtr node;
 | |
|     if ((reader == NULL) || (reader->node == NULL))
 | |
| 	return(NULL);
 | |
|     if (reader->curnode != NULL)
 | |
| 	node = reader->curnode;
 | |
|     else
 | |
| 	node = reader->node;
 | |
|     if (node->type == XML_NAMESPACE_DECL)
 | |
| 	return(constString(reader, BAD_CAST "http://www.w3.org/2000/xmlns/"));
 | |
|     if ((node->type != XML_ELEMENT_NODE) &&
 | |
| 	(node->type != XML_ATTRIBUTE_NODE))
 | |
| 	return(NULL);
 | |
|     if (node->ns != NULL)
 | |
| 	return(constString(reader, node->ns->href));
 | |
|     return(NULL);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderBaseUri:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * The base URI of the node.
 | |
|  *
 | |
|  * Returns the base URI or NULL if not available,
 | |
|  *    if non NULL it need to be freed by the caller.
 | |
|  */
 | |
| xmlChar *
 | |
| xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
 | |
|     xmlChar *ret = NULL;
 | |
|     int result;
 | |
| 
 | |
|     if ((reader == NULL) || (reader->node == NULL))
 | |
| 	return(NULL);
 | |
|     result = xmlNodeGetBaseSafe(NULL, reader->node, &ret);
 | |
|     if (result < 0)
 | |
|         xmlTextReaderErrMemory(reader);
 | |
| 
 | |
|     return(ret);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderConstBaseUri:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * The base URI of the node.
 | |
|  *
 | |
|  * Returns the base URI or NULL if not available, the string
 | |
|  *         will be deallocated with the reader
 | |
|  */
 | |
| const xmlChar *
 | |
| xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
 | |
|     xmlChar *tmp;
 | |
|     const xmlChar *ret;
 | |
|     int result;
 | |
| 
 | |
|     if ((reader == NULL) || (reader->node == NULL))
 | |
| 	return(NULL);
 | |
|     result = xmlNodeGetBaseSafe(NULL, reader->node, &tmp);
 | |
|     if (result < 0)
 | |
|         xmlTextReaderErrMemory(reader);
 | |
|     if (tmp == NULL)
 | |
|         return(NULL);
 | |
|     ret = constString(reader, tmp);
 | |
|     xmlFree(tmp);
 | |
|     return(ret);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderDepth:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * The depth of the node in the tree.
 | |
|  *
 | |
|  * Returns the depth or -1 in case of error
 | |
|  */
 | |
| int
 | |
| xmlTextReaderDepth(xmlTextReaderPtr reader) {
 | |
|     if (reader == NULL)
 | |
| 	return(-1);
 | |
|     if (reader->node == NULL)
 | |
| 	return(0);
 | |
| 
 | |
|     if (reader->curnode != NULL) {
 | |
| 	if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
 | |
| 	    (reader->curnode->type == XML_NAMESPACE_DECL))
 | |
| 	    return(reader->depth + 1);
 | |
| 	return(reader->depth + 2);
 | |
|     }
 | |
|     return(reader->depth);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderHasAttributes:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Whether the node has attributes.
 | |
|  *
 | |
|  * Returns 1 if true, 0 if false, and -1 in case or error
 | |
|  */
 | |
| int
 | |
| xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
 | |
|     xmlNodePtr node;
 | |
|     if (reader == NULL)
 | |
| 	return(-1);
 | |
|     if (reader->node == NULL)
 | |
| 	return(0);
 | |
|     if (reader->curnode != NULL)
 | |
| 	node = reader->curnode;
 | |
|     else
 | |
| 	node = reader->node;
 | |
| 
 | |
|     if ((node->type == XML_ELEMENT_NODE) &&
 | |
| 	((node->properties != NULL) || (node->nsDef != NULL)))
 | |
| 	return(1);
 | |
|     /* TODO: handle the xmlDecl */
 | |
|     return(0);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderHasValue:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Whether the node can have a text value.
 | |
|  *
 | |
|  * Returns 1 if true, 0 if false, and -1 in case or error
 | |
|  */
 | |
| int
 | |
| xmlTextReaderHasValue(xmlTextReaderPtr reader) {
 | |
|     xmlNodePtr node;
 | |
|     if (reader == NULL)
 | |
| 	return(-1);
 | |
|     if (reader->node == NULL)
 | |
| 	return(0);
 | |
|     if (reader->curnode != NULL)
 | |
| 	node = reader->curnode;
 | |
|     else
 | |
| 	node = reader->node;
 | |
| 
 | |
|     switch (node->type) {
 | |
|         case XML_ATTRIBUTE_NODE:
 | |
|         case XML_TEXT_NODE:
 | |
|         case XML_CDATA_SECTION_NODE:
 | |
|         case XML_PI_NODE:
 | |
|         case XML_COMMENT_NODE:
 | |
|         case XML_NAMESPACE_DECL:
 | |
| 	    return(1);
 | |
| 	default:
 | |
| 	    break;
 | |
|     }
 | |
|     return(0);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderValue:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Provides the text value of the node if present
 | |
|  *
 | |
|  * Returns the string or NULL if not available. The result must be deallocated
 | |
|  *     with xmlFree()
 | |
|  */
 | |
| xmlChar *
 | |
| xmlTextReaderValue(xmlTextReaderPtr reader) {
 | |
|     xmlNodePtr node;
 | |
|     if (reader == NULL)
 | |
| 	return(NULL);
 | |
|     if (reader->node == NULL)
 | |
| 	return(NULL);
 | |
|     if (reader->curnode != NULL)
 | |
| 	node = reader->curnode;
 | |
|     else
 | |
| 	node = reader->node;
 | |
| 
 | |
|     switch (node->type) {
 | |
|         case XML_NAMESPACE_DECL:
 | |
| 	    return(readerStrdup(reader, ((xmlNsPtr) node)->href));
 | |
|         case XML_ATTRIBUTE_NODE:{
 | |
| 	    xmlAttrPtr attr = (xmlAttrPtr) node;
 | |
|             xmlDocPtr doc = NULL;
 | |
|             xmlChar *ret;
 | |
| 
 | |
| 	    if (attr->parent != NULL)
 | |
|                 doc = attr->parent->doc;
 | |
| 	    ret = xmlNodeListGetString(doc, attr->children, 1);
 | |
|             if (ret == NULL)
 | |
|                 xmlTextReaderErrMemory(reader);
 | |
| 	    return(ret);
 | |
| 	}
 | |
|         case XML_TEXT_NODE:
 | |
|         case XML_CDATA_SECTION_NODE:
 | |
|         case XML_PI_NODE:
 | |
|         case XML_COMMENT_NODE:
 | |
|             return(readerStrdup(reader, node->content));
 | |
| 	default:
 | |
| 	    break;
 | |
|     }
 | |
|     return(NULL);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderConstValue:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Provides the text value of the node if present
 | |
|  *
 | |
|  * Returns the string or NULL if not available. The result will be
 | |
|  *     deallocated on the next Read() operation.
 | |
|  */
 | |
| const xmlChar *
 | |
| xmlTextReaderConstValue(xmlTextReaderPtr reader) {
 | |
|     xmlNodePtr node;
 | |
|     if (reader == NULL)
 | |
| 	return(NULL);
 | |
|     if (reader->node == NULL)
 | |
| 	return(NULL);
 | |
|     if (reader->curnode != NULL)
 | |
| 	node = reader->curnode;
 | |
|     else
 | |
| 	node = reader->node;
 | |
| 
 | |
|     switch (node->type) {
 | |
|         case XML_NAMESPACE_DECL:
 | |
| 	    return(((xmlNsPtr) node)->href);
 | |
|         case XML_ATTRIBUTE_NODE:{
 | |
| 	    xmlAttrPtr attr = (xmlAttrPtr) node;
 | |
| 	    const xmlChar *ret;
 | |
| 
 | |
| 	    if ((attr->children != NULL) &&
 | |
| 	        (attr->children->type == XML_TEXT_NODE) &&
 | |
| 		(attr->children->next == NULL))
 | |
| 		return(attr->children->content);
 | |
| 	    else {
 | |
| 		if (reader->buffer == NULL) {
 | |
| 		    reader->buffer = xmlBufCreate(50);
 | |
|                     if (reader->buffer == NULL)
 | |
|                         return (NULL);
 | |
|                 } else
 | |
|                     xmlBufEmpty(reader->buffer);
 | |
| 	        xmlBufGetNodeContent(reader->buffer, node);
 | |
| 		ret = xmlBufContent(reader->buffer);
 | |
| 		if (ret == NULL) {
 | |
|                     xmlTextReaderErrMemory(reader);
 | |
| 		    /* error on the buffer best to reallocate */
 | |
| 		    xmlBufFree(reader->buffer);
 | |
| 		    reader->buffer = xmlBufCreate(50);
 | |
| 		}
 | |
| 		return(ret);
 | |
| 	    }
 | |
| 	    break;
 | |
| 	}
 | |
|         case XML_TEXT_NODE:
 | |
|         case XML_CDATA_SECTION_NODE:
 | |
|         case XML_PI_NODE:
 | |
|         case XML_COMMENT_NODE:
 | |
| 	    return(node->content);
 | |
| 	default:
 | |
| 	    break;
 | |
|     }
 | |
|     return(NULL);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderIsDefault:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Whether an Attribute  node was generated from the default value
 | |
|  * defined in the DTD or schema.
 | |
|  *
 | |
|  * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
 | |
|  */
 | |
| int
 | |
| xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
 | |
|     if (reader == NULL)
 | |
| 	return(-1);
 | |
|     return(0);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderQuoteChar:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * The quotation mark character used to enclose the value of an attribute.
 | |
|  *
 | |
|  * Returns " or ' and -1 in case of error
 | |
|  */
 | |
| int
 | |
| xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
 | |
|     if (reader == NULL)
 | |
| 	return(-1);
 | |
|     /* TODO maybe lookup the attribute value for " first */
 | |
|     return('"');
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderXmlLang:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * The xml:lang scope within which the node resides.
 | |
|  *
 | |
|  * Returns the xml:lang value or NULL if none exists.,
 | |
|  *    if non NULL it need to be freed by the caller.
 | |
|  */
 | |
| xmlChar *
 | |
| xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
 | |
|     if (reader == NULL)
 | |
| 	return(NULL);
 | |
|     if (reader->node == NULL)
 | |
| 	return(NULL);
 | |
|     return(xmlNodeGetLang(reader->node));
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderConstXmlLang:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * The xml:lang scope within which the node resides.
 | |
|  *
 | |
|  * Returns the xml:lang value or NULL if none exists.
 | |
|  */
 | |
| const xmlChar *
 | |
| xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
 | |
|     xmlChar *tmp;
 | |
|     const xmlChar *ret;
 | |
| 
 | |
|     if (reader == NULL)
 | |
| 	return(NULL);
 | |
|     if (reader->node == NULL)
 | |
| 	return(NULL);
 | |
|     tmp = xmlNodeGetLang(reader->node);
 | |
|     if (tmp == NULL)
 | |
|         return(NULL);
 | |
|     ret = constString(reader, tmp);
 | |
|     xmlFree(tmp);
 | |
|     return(ret);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderConstString:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @str:  the string to intern.
 | |
|  *
 | |
|  * Get an interned string from the reader, allows for example to
 | |
|  * speedup string name comparisons
 | |
|  *
 | |
|  * Returns an interned copy of the string or NULL in case of error. The
 | |
|  *         string will be deallocated with the reader.
 | |
|  */
 | |
| const xmlChar *
 | |
| xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
 | |
|     if (reader == NULL)
 | |
| 	return(NULL);
 | |
|     return(constString(reader, str));
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderNormalization:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * The value indicating whether to normalize white space and attribute values.
 | |
|  * Since attribute value and end of line normalizations are a MUST in the XML
 | |
|  * specification only the value true is accepted. The broken behaviour of
 | |
|  * accepting out of range character entities like � is of course not
 | |
|  * supported either.
 | |
|  *
 | |
|  * Returns 1 or -1 in case of error.
 | |
|  */
 | |
| int
 | |
| xmlTextReaderNormalization(xmlTextReaderPtr reader) {
 | |
|     if (reader == NULL)
 | |
| 	return(-1);
 | |
|     return(1);
 | |
| }
 | |
| 
 | |
| /************************************************************************
 | |
|  *									*
 | |
|  *			Extensions to the base APIs			*
 | |
|  *									*
 | |
|  ************************************************************************/
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderSetParserProp:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @prop:  the xmlParserProperties to set
 | |
|  * @value:  usually 0 or 1 to (de)activate it
 | |
|  *
 | |
|  * Change the parser processing behaviour by changing some of its internal
 | |
|  * properties. Note that some properties can only be changed before any
 | |
|  * read has been done.
 | |
|  *
 | |
|  * Returns 0 if the call was successful, or -1 in case of error
 | |
|  */
 | |
| int
 | |
| xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
 | |
|     xmlParserProperties p = (xmlParserProperties) prop;
 | |
|     xmlParserCtxtPtr ctxt;
 | |
| 
 | |
|     if ((reader == NULL) || (reader->ctxt == NULL))
 | |
| 	return(-1);
 | |
|     ctxt = reader->ctxt;
 | |
| 
 | |
|     switch (p) {
 | |
|         case XML_PARSER_LOADDTD:
 | |
| 	    if (value != 0) {
 | |
| 		if (ctxt->loadsubset == 0) {
 | |
| 		    if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
 | |
| 			return(-1);
 | |
|                     ctxt->options |= XML_PARSE_DTDLOAD;
 | |
| 		    ctxt->loadsubset |= XML_DETECT_IDS;
 | |
| 		}
 | |
| 	    } else {
 | |
|                 ctxt->options &= ~XML_PARSE_DTDLOAD;
 | |
| 		ctxt->loadsubset &= ~XML_DETECT_IDS;
 | |
| 	    }
 | |
| 	    return(0);
 | |
|         case XML_PARSER_DEFAULTATTRS:
 | |
| 	    if (value != 0) {
 | |
|                 ctxt->options |= XML_PARSE_DTDATTR;
 | |
| 		ctxt->loadsubset |= XML_COMPLETE_ATTRS;
 | |
| 	    } else {
 | |
|                 ctxt->options &= ~XML_PARSE_DTDATTR;
 | |
| 		ctxt->loadsubset &= ~XML_COMPLETE_ATTRS;
 | |
| 	    }
 | |
| 	    return(0);
 | |
|         case XML_PARSER_VALIDATE:
 | |
| 	    if (value != 0) {
 | |
|                 ctxt->options |= XML_PARSE_DTDVALID;
 | |
| 		ctxt->validate = 1;
 | |
| 		reader->validate = XML_TEXTREADER_VALIDATE_DTD;
 | |
| 	    } else {
 | |
|                 ctxt->options &= ~XML_PARSE_DTDVALID;
 | |
| 		ctxt->validate = 0;
 | |
| 	    }
 | |
| 	    return(0);
 | |
|         case XML_PARSER_SUBST_ENTITIES:
 | |
| 	    if (value != 0) {
 | |
|                 ctxt->options |= XML_PARSE_NOENT;
 | |
| 		ctxt->replaceEntities = 1;
 | |
| 	    } else {
 | |
|                 ctxt->options &= ~XML_PARSE_NOENT;
 | |
| 		ctxt->replaceEntities = 0;
 | |
| 	    }
 | |
| 	    return(0);
 | |
|     }
 | |
|     return(-1);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderGetParserProp:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @prop:  the xmlParserProperties to get
 | |
|  *
 | |
|  * Read the parser internal property.
 | |
|  *
 | |
|  * Returns the value, usually 0 or 1, or -1 in case of error.
 | |
|  */
 | |
| int
 | |
| xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
 | |
|     xmlParserProperties p = (xmlParserProperties) prop;
 | |
|     xmlParserCtxtPtr ctxt;
 | |
| 
 | |
|     if ((reader == NULL) || (reader->ctxt == NULL))
 | |
| 	return(-1);
 | |
|     ctxt = reader->ctxt;
 | |
| 
 | |
|     switch (p) {
 | |
|         case XML_PARSER_LOADDTD:
 | |
| 	    if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
 | |
| 		return(1);
 | |
| 	    return(0);
 | |
|         case XML_PARSER_DEFAULTATTRS:
 | |
| 	    if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
 | |
| 		return(1);
 | |
| 	    return(0);
 | |
|         case XML_PARSER_VALIDATE:
 | |
| 	    return(reader->validate);
 | |
| 	case XML_PARSER_SUBST_ENTITIES:
 | |
| 	    return(ctxt->replaceEntities);
 | |
|     }
 | |
|     return(-1);
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderGetParserLineNumber:
 | |
|  * @reader: the user data (XML reader context)
 | |
|  *
 | |
|  * Provide the line number of the current parsing point.
 | |
|  *
 | |
|  * Returns an int or 0 if not available
 | |
|  */
 | |
| int
 | |
| xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
 | |
| {
 | |
|     if ((reader == NULL) || (reader->ctxt == NULL) ||
 | |
|         (reader->ctxt->input == NULL)) {
 | |
|         return (0);
 | |
|     }
 | |
|     return (reader->ctxt->input->line);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderGetParserColumnNumber:
 | |
|  * @reader: the user data (XML reader context)
 | |
|  *
 | |
|  * Provide the column number of the current parsing point.
 | |
|  *
 | |
|  * Returns an int or 0 if not available
 | |
|  */
 | |
| int
 | |
| xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
 | |
| {
 | |
|     if ((reader == NULL) || (reader->ctxt == NULL) ||
 | |
|         (reader->ctxt->input == NULL)) {
 | |
|         return (0);
 | |
|     }
 | |
|     return (reader->ctxt->input->col);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderCurrentNode:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Hacking interface allowing to get the xmlNodePtr corresponding to the
 | |
|  * current node being accessed by the xmlTextReader. This is dangerous
 | |
|  * because the underlying node may be destroyed on the next Reads.
 | |
|  *
 | |
|  * Returns the xmlNodePtr or NULL in case of error.
 | |
|  */
 | |
| xmlNodePtr
 | |
| xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
 | |
|     if (reader == NULL)
 | |
| 	return(NULL);
 | |
| 
 | |
|     if (reader->curnode != NULL)
 | |
| 	return(reader->curnode);
 | |
|     return(reader->node);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderPreserve:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * This tells the XML Reader to preserve the current node.
 | |
|  * The caller must also use xmlTextReaderCurrentDoc() to
 | |
|  * keep an handle on the resulting document once parsing has finished
 | |
|  *
 | |
|  * Returns the xmlNodePtr or NULL in case of error.
 | |
|  */
 | |
| xmlNodePtr
 | |
| xmlTextReaderPreserve(xmlTextReaderPtr reader) {
 | |
|     xmlNodePtr cur, parent;
 | |
| 
 | |
|     if (reader == NULL)
 | |
| 	return(NULL);
 | |
| 
 | |
|     cur = reader->node;
 | |
|     if (cur == NULL)
 | |
|         return(NULL);
 | |
| 
 | |
|     if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
 | |
| 	cur->extra |= NODE_IS_PRESERVED;
 | |
| 	cur->extra |= NODE_IS_SPRESERVED;
 | |
|     }
 | |
|     reader->preserves++;
 | |
| 
 | |
|     parent = cur->parent;;
 | |
|     while (parent != NULL) {
 | |
|         if (parent->type == XML_ELEMENT_NODE)
 | |
| 	    parent->extra |= NODE_IS_PRESERVED;
 | |
| 	parent = parent->parent;
 | |
|     }
 | |
|     return(cur);
 | |
| }
 | |
| 
 | |
| #ifdef LIBXML_PATTERN_ENABLED
 | |
| /**
 | |
|  * xmlTextReaderPreservePattern:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @pattern:  an XPath subset pattern
 | |
|  * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
 | |
|  *
 | |
|  * This tells the XML Reader to preserve all nodes matched by the
 | |
|  * pattern. The caller must also use xmlTextReaderCurrentDoc() to
 | |
|  * keep an handle on the resulting document once parsing has finished
 | |
|  *
 | |
|  * Returns a non-negative number in case of success and -1 in case of error
 | |
|  */
 | |
| int
 | |
| xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
 | |
|                              const xmlChar **namespaces)
 | |
| {
 | |
|     xmlPatternPtr comp;
 | |
| 
 | |
|     if ((reader == NULL) || (pattern == NULL))
 | |
| 	return(-1);
 | |
| 
 | |
|     comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
 | |
|     if (comp == NULL)
 | |
|         return(-1);
 | |
| 
 | |
|     if (reader->patternMax <= 0) {
 | |
| 	reader->patternMax = 4;
 | |
| 	reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
 | |
| 					      sizeof(reader->patternTab[0]));
 | |
|         if (reader->patternTab == NULL) {
 | |
|             xmlTextReaderErrMemory(reader);
 | |
|             return (-1);
 | |
|         }
 | |
|     }
 | |
|     if (reader->patternNr >= reader->patternMax) {
 | |
|         xmlPatternPtr *tmp;
 | |
|         reader->patternMax *= 2;
 | |
| 	tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
 | |
|                                       reader->patternMax *
 | |
|                                       sizeof(reader->patternTab[0]));
 | |
|         if (tmp == NULL) {
 | |
|             xmlTextReaderErrMemory(reader);
 | |
| 	    reader->patternMax /= 2;
 | |
|             return (-1);
 | |
|         }
 | |
| 	reader->patternTab = tmp;
 | |
|     }
 | |
|     reader->patternTab[reader->patternNr] = comp;
 | |
|     return(reader->patternNr++);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderCurrentDoc:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Hacking interface allowing to get the xmlDocPtr corresponding to the
 | |
|  * current document being accessed by the xmlTextReader.
 | |
|  * NOTE: as a result of this call, the reader will not destroy the
 | |
|  *       associated XML document and calling xmlFreeDoc() on the result
 | |
|  *       is needed once the reader parsing has finished.
 | |
|  *
 | |
|  * Returns the xmlDocPtr or NULL in case of error.
 | |
|  */
 | |
| xmlDocPtr
 | |
| xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
 | |
|     if (reader == NULL)
 | |
| 	return(NULL);
 | |
|     if (reader->doc != NULL)
 | |
|         return(reader->doc);
 | |
|     if ((reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL))
 | |
| 	return(NULL);
 | |
| 
 | |
|     reader->preserve = 1;
 | |
|     return(reader->ctxt->myDoc);
 | |
| }
 | |
| 
 | |
| #ifdef LIBXML_SCHEMAS_ENABLED
 | |
| /**
 | |
|  * xmlTextReaderRelaxNGSetSchema:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @schema:  a precompiled RelaxNG schema
 | |
|  *
 | |
|  * Use RelaxNG to validate the document as it is processed.
 | |
|  * Activation is only possible before the first Read().
 | |
|  * if @schema is NULL, then RelaxNG validation is deactivated.
 | |
|  @ The @schema should not be freed until the reader is deallocated
 | |
|  * or its use has been deactivated.
 | |
|  *
 | |
|  * Returns 0 in case the RelaxNG validation could be (de)activated and
 | |
|  *         -1 in case of error.
 | |
|  */
 | |
| int
 | |
| xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
 | |
|     if (reader == NULL)
 | |
|         return(-1);
 | |
|     if (schema == NULL) {
 | |
|         if (reader->rngSchemas != NULL) {
 | |
| 	    xmlRelaxNGFree(reader->rngSchemas);
 | |
| 	    reader->rngSchemas = NULL;
 | |
| 	}
 | |
|         if (reader->rngValidCtxt != NULL) {
 | |
| 	    if (! reader->rngPreserveCtxt)
 | |
| 		xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
 | |
| 	    reader->rngValidCtxt = NULL;
 | |
|         }
 | |
| 	reader->rngPreserveCtxt = 0;
 | |
| 	return(0);
 | |
|     }
 | |
|     if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
 | |
| 	return(-1);
 | |
|     if (reader->rngSchemas != NULL) {
 | |
| 	xmlRelaxNGFree(reader->rngSchemas);
 | |
| 	reader->rngSchemas = NULL;
 | |
|     }
 | |
|     if (reader->rngValidCtxt != NULL) {
 | |
| 	if (! reader->rngPreserveCtxt)
 | |
| 	    xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
 | |
| 	reader->rngValidCtxt = NULL;
 | |
|     }
 | |
|     reader->rngPreserveCtxt = 0;
 | |
|     reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
 | |
|     if (reader->rngValidCtxt == NULL)
 | |
|         return(-1);
 | |
|     if ((reader->errorFunc != NULL) || (reader->sErrorFunc != NULL))
 | |
| 	xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
 | |
| 			xmlTextReaderStructuredRelay, reader);
 | |
|     reader->rngValidErrors = 0;
 | |
|     reader->rngFullNode = NULL;
 | |
|     reader->validate = XML_TEXTREADER_VALIDATE_RNG;
 | |
|     return(0);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderLocator:
 | |
|  * @ctx: the xmlTextReaderPtr used
 | |
|  * @file: returned file information
 | |
|  * @line: returned line information
 | |
|  *
 | |
|  * Internal locator function for the readers
 | |
|  *
 | |
|  * Returns 0 in case the Schema validation could be (de)activated and
 | |
|  *         -1 in case of error.
 | |
|  */
 | |
| static int
 | |
| xmlTextReaderLocator(void *ctx, const char **file, unsigned long *line) {
 | |
|     xmlTextReaderPtr reader;
 | |
| 
 | |
|     if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
 | |
|         return(-1);
 | |
| 
 | |
|     if (file != NULL)
 | |
|         *file = NULL;
 | |
|     if (line != NULL)
 | |
|         *line = 0;
 | |
| 
 | |
|     reader = (xmlTextReaderPtr) ctx;
 | |
|     if ((reader->ctxt != NULL) && (reader->ctxt->input != NULL)) {
 | |
| 	if (file != NULL)
 | |
| 	    *file = reader->ctxt->input->filename;
 | |
| 	if (line != NULL)
 | |
| 	    *line = reader->ctxt->input->line;
 | |
| 	return(0);
 | |
|     }
 | |
|     if (reader->node != NULL) {
 | |
|         long res;
 | |
| 	int ret = 0;
 | |
| 
 | |
| 	if (line != NULL) {
 | |
| 	    res = xmlGetLineNo(reader->node);
 | |
| 	    if (res > 0)
 | |
| 	        *line = (unsigned long) res;
 | |
| 	    else
 | |
|                 ret = -1;
 | |
| 	}
 | |
|         if (file != NULL) {
 | |
| 	    xmlDocPtr doc = reader->node->doc;
 | |
| 	    if ((doc != NULL) && (doc->URL != NULL))
 | |
| 	        *file = (const char *) doc->URL;
 | |
| 	    else
 | |
|                 ret = -1;
 | |
| 	}
 | |
| 	return(ret);
 | |
|     }
 | |
|     return(-1);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderSetSchema:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @schema:  a precompiled Schema schema
 | |
|  *
 | |
|  * Use XSD Schema to validate the document as it is processed.
 | |
|  * Activation is only possible before the first Read().
 | |
|  * if @schema is NULL, then Schema validation is deactivated.
 | |
|  * The @schema should not be freed until the reader is deallocated
 | |
|  * or its use has been deactivated.
 | |
|  *
 | |
|  * Returns 0 in case the Schema validation could be (de)activated and
 | |
|  *         -1 in case of error.
 | |
|  */
 | |
| int
 | |
| xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
 | |
|     if (reader == NULL)
 | |
|         return(-1);
 | |
|     if (schema == NULL) {
 | |
| 	if (reader->xsdPlug != NULL) {
 | |
| 	    xmlSchemaSAXUnplug(reader->xsdPlug);
 | |
| 	    reader->xsdPlug = NULL;
 | |
| 	}
 | |
|         if (reader->xsdValidCtxt != NULL) {
 | |
| 	    if (! reader->xsdPreserveCtxt)
 | |
| 		xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
 | |
| 	    reader->xsdValidCtxt = NULL;
 | |
|         }
 | |
| 	reader->xsdPreserveCtxt = 0;
 | |
|         if (reader->xsdSchemas != NULL) {
 | |
| 	    xmlSchemaFree(reader->xsdSchemas);
 | |
| 	    reader->xsdSchemas = NULL;
 | |
| 	}
 | |
| 	return(0);
 | |
|     }
 | |
|     if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
 | |
| 	return(-1);
 | |
|     if (reader->xsdPlug != NULL) {
 | |
| 	xmlSchemaSAXUnplug(reader->xsdPlug);
 | |
| 	reader->xsdPlug = NULL;
 | |
|     }
 | |
|     if (reader->xsdValidCtxt != NULL) {
 | |
| 	if (! reader->xsdPreserveCtxt)
 | |
| 	    xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
 | |
| 	reader->xsdValidCtxt = NULL;
 | |
|     }
 | |
|     reader->xsdPreserveCtxt = 0;
 | |
|     if (reader->xsdSchemas != NULL) {
 | |
| 	xmlSchemaFree(reader->xsdSchemas);
 | |
| 	reader->xsdSchemas = NULL;
 | |
|     }
 | |
|     reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
 | |
|     if (reader->xsdValidCtxt == NULL) {
 | |
| 	xmlSchemaFree(reader->xsdSchemas);
 | |
| 	reader->xsdSchemas = NULL;
 | |
|         return(-1);
 | |
|     }
 | |
|     reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
 | |
|                                        &(reader->ctxt->sax),
 | |
| 				       &(reader->ctxt->userData));
 | |
|     if (reader->xsdPlug == NULL) {
 | |
| 	xmlSchemaFree(reader->xsdSchemas);
 | |
| 	reader->xsdSchemas = NULL;
 | |
| 	xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
 | |
| 	reader->xsdValidCtxt = NULL;
 | |
| 	return(-1);
 | |
|     }
 | |
|     xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
 | |
|                                 xmlTextReaderLocator,
 | |
| 				(void *) reader);
 | |
| 
 | |
|     if ((reader->errorFunc != NULL) || (reader->sErrorFunc != NULL))
 | |
| 	xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
 | |
| 			xmlTextReaderStructuredRelay, reader);
 | |
|     reader->xsdValidErrors = 0;
 | |
|     reader->validate = XML_TEXTREADER_VALIDATE_XSD;
 | |
|     return(0);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderRelaxNGValidateInternal:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @rng:  the path to a RelaxNG schema or NULL
 | |
|  * @ctxt: the RelaxNG schema validation context or NULL
 | |
|  * @options: options (not yet used)
 | |
|  *
 | |
|  * Use RelaxNG to validate the document as it is processed.
 | |
|  * Activation is only possible before the first Read().
 | |
|  * If both @rng and @ctxt are NULL, then RelaxNG validation is deactivated.
 | |
|  *
 | |
|  * Returns 0 in case the RelaxNG validation could be (de)activated and
 | |
|  *	   -1 in case of error.
 | |
|  */
 | |
| static int
 | |
| xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader,
 | |
| 				     const char *rng,
 | |
| 				     xmlRelaxNGValidCtxtPtr ctxt,
 | |
| 				     int options ATTRIBUTE_UNUSED)
 | |
| {
 | |
|     if (reader == NULL)
 | |
| 	return(-1);
 | |
| 
 | |
|     if ((rng != NULL) && (ctxt != NULL))
 | |
| 	return (-1);
 | |
| 
 | |
|     if (((rng != NULL) || (ctxt != NULL)) &&
 | |
| 	((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
 | |
| 	 (reader->ctxt == NULL)))
 | |
| 	return(-1);
 | |
| 
 | |
|     /* Cleanup previous validation stuff. */
 | |
|     if (reader->rngValidCtxt != NULL) {
 | |
| 	if ( !reader->rngPreserveCtxt)
 | |
| 	    xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
 | |
| 	reader->rngValidCtxt = NULL;
 | |
|     }
 | |
|     reader->rngPreserveCtxt = 0;
 | |
|     if (reader->rngSchemas != NULL) {
 | |
| 	xmlRelaxNGFree(reader->rngSchemas);
 | |
| 	reader->rngSchemas = NULL;
 | |
|     }
 | |
| 
 | |
|     if ((rng == NULL) && (ctxt == NULL)) {
 | |
| 	/* We just want to deactivate the validation, so get out. */
 | |
| 	return(0);
 | |
|     }
 | |
| 
 | |
| 
 | |
|     if (rng != NULL) {
 | |
| 	xmlRelaxNGParserCtxtPtr pctxt;
 | |
| 	/* Parse the schema and create validation environment. */
 | |
| 
 | |
| 	pctxt = xmlRelaxNGNewParserCtxt(rng);
 | |
| 	if ((reader->errorFunc != NULL) || (reader->sErrorFunc != NULL))
 | |
| 	    xmlRelaxNGSetParserStructuredErrors(pctxt,
 | |
|                     xmlTextReaderStructuredRelay, reader);
 | |
| 	reader->rngSchemas = xmlRelaxNGParse(pctxt);
 | |
| 	xmlRelaxNGFreeParserCtxt(pctxt);
 | |
| 	if (reader->rngSchemas == NULL)
 | |
| 	    return(-1);
 | |
| 
 | |
| 	reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
 | |
| 	if (reader->rngValidCtxt == NULL) {
 | |
| 	    xmlRelaxNGFree(reader->rngSchemas);
 | |
| 	    reader->rngSchemas = NULL;
 | |
| 	    return(-1);
 | |
| 	}
 | |
|     } else {
 | |
| 	/* Use the given validation context. */
 | |
| 	reader->rngValidCtxt = ctxt;
 | |
| 	reader->rngPreserveCtxt = 1;
 | |
|     }
 | |
|     /*
 | |
|     * Redirect the validation context's error channels to use
 | |
|     * the reader channels.
 | |
|     * TODO: In case the user provides the validation context we
 | |
|     *	could make this redirection optional.
 | |
|     */
 | |
|     if ((reader->errorFunc != NULL) || (reader->sErrorFunc != NULL))
 | |
|         xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
 | |
|                 xmlTextReaderStructuredRelay, reader);
 | |
|     reader->rngValidErrors = 0;
 | |
|     reader->rngFullNode = NULL;
 | |
|     reader->validate = XML_TEXTREADER_VALIDATE_RNG;
 | |
|     return(0);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderSchemaValidateInternal:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @xsd:  the path to a W3C XSD schema or NULL
 | |
|  * @ctxt: the XML Schema validation context or NULL
 | |
|  * @options: options (not used yet)
 | |
|  *
 | |
|  * Validate the document as it is processed using XML Schema.
 | |
|  * Activation is only possible before the first Read().
 | |
|  * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated.
 | |
|  *
 | |
|  * Returns 0 in case the schemas validation could be (de)activated and
 | |
|  *         -1 in case of error.
 | |
|  */
 | |
| static int
 | |
| xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
 | |
| 				    const char *xsd,
 | |
| 				    xmlSchemaValidCtxtPtr ctxt,
 | |
| 				    int options ATTRIBUTE_UNUSED)
 | |
| {
 | |
|     if (reader == NULL)
 | |
|         return(-1);
 | |
| 
 | |
|     if ((xsd != NULL) && (ctxt != NULL))
 | |
| 	return(-1);
 | |
| 
 | |
|     if (((xsd != NULL) || (ctxt != NULL)) &&
 | |
| 	((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
 | |
|         (reader->ctxt == NULL)))
 | |
| 	return(-1);
 | |
| 
 | |
|     /* Cleanup previous validation stuff. */
 | |
|     if (reader->xsdPlug != NULL) {
 | |
| 	xmlSchemaSAXUnplug(reader->xsdPlug);
 | |
| 	reader->xsdPlug = NULL;
 | |
|     }
 | |
|     if (reader->xsdValidCtxt != NULL) {
 | |
| 	if (! reader->xsdPreserveCtxt)
 | |
| 	    xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
 | |
| 	reader->xsdValidCtxt = NULL;
 | |
|     }
 | |
|     reader->xsdPreserveCtxt = 0;
 | |
|     if (reader->xsdSchemas != NULL) {
 | |
| 	xmlSchemaFree(reader->xsdSchemas);
 | |
| 	reader->xsdSchemas = NULL;
 | |
|     }
 | |
| 
 | |
|     if ((xsd == NULL) && (ctxt == NULL)) {
 | |
| 	/* We just want to deactivate the validation, so get out. */
 | |
| 	return(0);
 | |
|     }
 | |
| 
 | |
|     if (xsd != NULL) {
 | |
| 	xmlSchemaParserCtxtPtr pctxt;
 | |
| 	/* Parse the schema and create validation environment. */
 | |
| 	pctxt = xmlSchemaNewParserCtxt(xsd);
 | |
| 	if ((reader->errorFunc != NULL) || (reader->sErrorFunc != NULL))
 | |
| 	    xmlSchemaSetParserStructuredErrors(pctxt,
 | |
|                     xmlTextReaderStructuredRelay, reader);
 | |
| 	reader->xsdSchemas = xmlSchemaParse(pctxt);
 | |
| 	xmlSchemaFreeParserCtxt(pctxt);
 | |
| 	if (reader->xsdSchemas == NULL)
 | |
| 	    return(-1);
 | |
| 	reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
 | |
| 	if (reader->xsdValidCtxt == NULL) {
 | |
| 	    xmlSchemaFree(reader->xsdSchemas);
 | |
| 	    reader->xsdSchemas = NULL;
 | |
| 	    return(-1);
 | |
| 	}
 | |
| 	reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
 | |
| 	    &(reader->ctxt->sax),
 | |
| 	    &(reader->ctxt->userData));
 | |
| 	if (reader->xsdPlug == NULL) {
 | |
| 	    xmlSchemaFree(reader->xsdSchemas);
 | |
| 	    reader->xsdSchemas = NULL;
 | |
| 	    xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
 | |
| 	    reader->xsdValidCtxt = NULL;
 | |
| 	    return(-1);
 | |
| 	}
 | |
|     } else {
 | |
| 	/* Use the given validation context. */
 | |
| 	reader->xsdValidCtxt = ctxt;
 | |
| 	reader->xsdPreserveCtxt = 1;
 | |
| 	reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
 | |
| 	    &(reader->ctxt->sax),
 | |
| 	    &(reader->ctxt->userData));
 | |
| 	if (reader->xsdPlug == NULL) {
 | |
| 	    reader->xsdValidCtxt = NULL;
 | |
| 	    reader->xsdPreserveCtxt = 0;
 | |
| 	    return(-1);
 | |
| 	}
 | |
|     }
 | |
|     xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
 | |
|                                 xmlTextReaderLocator,
 | |
| 				(void *) reader);
 | |
|     /*
 | |
|     * Redirect the validation context's error channels to use
 | |
|     * the reader channels.
 | |
|     * TODO: In case the user provides the validation context we
 | |
|     *   could make this redirection optional.
 | |
|     */
 | |
|     if ((reader->errorFunc != NULL) || (reader->sErrorFunc != NULL))
 | |
| 	xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
 | |
| 			xmlTextReaderStructuredRelay, reader);
 | |
|     reader->xsdValidErrors = 0;
 | |
|     reader->validate = XML_TEXTREADER_VALIDATE_XSD;
 | |
|     return(0);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderSchemaValidateCtxt:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @ctxt: the XML Schema validation context or NULL
 | |
|  * @options: options (not used yet)
 | |
|  *
 | |
|  * Use W3C XSD schema context to validate the document as it is processed.
 | |
|  * Activation is only possible before the first Read().
 | |
|  * If @ctxt is NULL, then XML Schema validation is deactivated.
 | |
|  *
 | |
|  * Returns 0 in case the schemas validation could be (de)activated and
 | |
|  *         -1 in case of error.
 | |
|  */
 | |
| int
 | |
| xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,
 | |
| 				    xmlSchemaValidCtxtPtr ctxt,
 | |
| 				    int options)
 | |
| {
 | |
|     return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options));
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderSchemaValidate:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @xsd:  the path to a W3C XSD schema or NULL
 | |
|  *
 | |
|  * Use W3C XSD schema to validate the document as it is processed.
 | |
|  * Activation is only possible before the first Read().
 | |
|  * If @xsd is NULL, then XML Schema validation is deactivated.
 | |
|  *
 | |
|  * Returns 0 in case the schemas validation could be (de)activated and
 | |
|  *         -1 in case of error.
 | |
|  */
 | |
| int
 | |
| xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd)
 | |
| {
 | |
|     return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderRelaxNGValidateCtxt:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @ctxt: the RelaxNG schema validation context or NULL
 | |
|  * @options: options (not used yet)
 | |
|  *
 | |
|  * Use RelaxNG schema context to validate the document as it is processed.
 | |
|  * Activation is only possible before the first Read().
 | |
|  * If @ctxt is NULL, then RelaxNG schema validation is deactivated.
 | |
|  *
 | |
|  * Returns 0 in case the schemas validation could be (de)activated and
 | |
|  *         -1 in case of error.
 | |
|  */
 | |
| int
 | |
| xmlTextReaderRelaxNGValidateCtxt(xmlTextReaderPtr reader,
 | |
| 				 xmlRelaxNGValidCtxtPtr ctxt,
 | |
| 				 int options)
 | |
| {
 | |
|     return(xmlTextReaderRelaxNGValidateInternal(reader, NULL, ctxt, options));
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderRelaxNGValidate:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @rng:  the path to a RelaxNG schema or NULL
 | |
|  *
 | |
|  * Use RelaxNG schema to validate the document as it is processed.
 | |
|  * Activation is only possible before the first Read().
 | |
|  * If @rng is NULL, then RelaxNG schema validation is deactivated.
 | |
|  *
 | |
|  * Returns 0 in case the schemas validation could be (de)activated and
 | |
|  *         -1 in case of error.
 | |
|  */
 | |
| int
 | |
| xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng)
 | |
| {
 | |
|     return(xmlTextReaderRelaxNGValidateInternal(reader, rng, NULL, 0));
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderIsNamespaceDecl:
 | |
|  * @reader: the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Determine whether the current node is a namespace declaration
 | |
|  * rather than a regular attribute.
 | |
|  *
 | |
|  * Returns 1 if the current node is a namespace declaration, 0 if it
 | |
|  * is a regular attribute or other type of node, or -1 in case of
 | |
|  * error.
 | |
|  */
 | |
| int
 | |
| xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
 | |
|     xmlNodePtr node;
 | |
|     if (reader == NULL)
 | |
| 	return(-1);
 | |
|     if (reader->node == NULL)
 | |
| 	return(-1);
 | |
|     if (reader->curnode != NULL)
 | |
| 	node = reader->curnode;
 | |
|     else
 | |
| 	node = reader->node;
 | |
| 
 | |
|     if (XML_NAMESPACE_DECL == node->type)
 | |
| 	return(1);
 | |
|     else
 | |
| 	return(0);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderConstXmlVersion:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Determine the XML version of the document being read.
 | |
|  *
 | |
|  * Returns a string containing the XML version of the document or NULL
 | |
|  * in case of error.  The string is deallocated with the reader.
 | |
|  */
 | |
| const xmlChar *
 | |
| xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
 | |
|     xmlDocPtr doc = NULL;
 | |
|     if (reader == NULL)
 | |
| 	return(NULL);
 | |
|     if (reader->doc != NULL)
 | |
|         doc = reader->doc;
 | |
|     else if (reader->ctxt != NULL)
 | |
| 	doc = reader->ctxt->myDoc;
 | |
|     if (doc == NULL)
 | |
| 	return(NULL);
 | |
| 
 | |
|     if (doc->version == NULL)
 | |
| 	return(NULL);
 | |
|     else
 | |
|       return(constString(reader, doc->version));
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderStandalone:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Determine the standalone status of the document being read.
 | |
|  *
 | |
|  * Returns 1 if the document was declared to be standalone, 0 if it
 | |
|  * was declared to be not standalone, or -1 if the document did not
 | |
|  * specify its standalone status or in case of error.
 | |
|  */
 | |
| int
 | |
| xmlTextReaderStandalone(xmlTextReaderPtr reader) {
 | |
|     xmlDocPtr doc = NULL;
 | |
|     if (reader == NULL)
 | |
| 	return(-1);
 | |
|     if (reader->doc != NULL)
 | |
|         doc = reader->doc;
 | |
|     else if (reader->ctxt != NULL)
 | |
| 	doc = reader->ctxt->myDoc;
 | |
|     if (doc == NULL)
 | |
| 	return(-1);
 | |
| 
 | |
|     return(doc->standalone);
 | |
| }
 | |
| 
 | |
| /************************************************************************
 | |
|  *									*
 | |
|  *			Error Handling Extensions                       *
 | |
|  *									*
 | |
|  ************************************************************************/
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderLocatorLineNumber:
 | |
|  * @locator: the xmlTextReaderLocatorPtr used
 | |
|  *
 | |
|  * Obtain the line number for the given locator.
 | |
|  *
 | |
|  * Returns the line number or -1 in case of error.
 | |
|  */
 | |
| int
 | |
| xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
 | |
|     /* we know that locator is a xmlParserCtxtPtr */
 | |
|     xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
 | |
|     int ret = -1;
 | |
| 
 | |
|     if (locator == NULL)
 | |
|         return(-1);
 | |
|     if (ctx->node != NULL) {
 | |
| 	ret = xmlGetLineNo(ctx->node);
 | |
|     }
 | |
|     else {
 | |
| 	/* inspired from error.c */
 | |
| 	xmlParserInputPtr input;
 | |
| 	input = ctx->input;
 | |
| 	if ((input->filename == NULL) && (ctx->inputNr > 1))
 | |
| 	    input = ctx->inputTab[ctx->inputNr - 2];
 | |
| 	if (input != NULL) {
 | |
| 	    ret = input->line;
 | |
| 	}
 | |
| 	else {
 | |
| 	    ret = -1;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderLocatorBaseURI:
 | |
|  * @locator: the xmlTextReaderLocatorPtr used
 | |
|  *
 | |
|  * Obtain the base URI for the given locator.
 | |
|  *
 | |
|  * Returns the base URI or NULL in case of error,
 | |
|  *    if non NULL it need to be freed by the caller.
 | |
|  */
 | |
| xmlChar *
 | |
| xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
 | |
|     /* we know that locator is a xmlParserCtxtPtr */
 | |
|     xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
 | |
|     xmlChar *ret = NULL;
 | |
| 
 | |
|     if (locator == NULL)
 | |
|         return(NULL);
 | |
|     if (ctx->node != NULL) {
 | |
| 	ret = xmlNodeGetBase(NULL,ctx->node);
 | |
|     }
 | |
|     else {
 | |
| 	/* inspired from error.c */
 | |
| 	xmlParserInputPtr input;
 | |
| 	input = ctx->input;
 | |
| 	if ((input->filename == NULL) && (ctx->inputNr > 1))
 | |
| 	    input = ctx->inputTab[ctx->inputNr - 2];
 | |
| 	if (input != NULL) {
 | |
| 	    ret = xmlStrdup(BAD_CAST input->filename);
 | |
| 	}
 | |
| 	else {
 | |
| 	    ret = NULL;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderSetErrorHandler:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @f:	the callback function to call on error and warnings
 | |
|  * @arg:    a user argument to pass to the callback function
 | |
|  *
 | |
|  * DEPRECATED: Use xmlTextReaderSetStructuredErrorHandler.
 | |
|  *
 | |
|  * Register a callback function that will be called on error and warnings.
 | |
|  *
 | |
|  * If @f is NULL, the default error and warning handlers are restored.
 | |
|  */
 | |
| void
 | |
| xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
 | |
|                              xmlTextReaderErrorFunc f, void *arg)
 | |
| {
 | |
|     if (f != NULL) {
 | |
|         reader->errorFunc = f;
 | |
|         reader->sErrorFunc = NULL;
 | |
|         reader->errorFuncArg = arg;
 | |
|         xmlCtxtSetErrorHandler(reader->ctxt,
 | |
|                 xmlTextReaderStructuredRelay, reader);
 | |
| #ifdef LIBXML_SCHEMAS_ENABLED
 | |
|         if (reader->rngValidCtxt) {
 | |
|             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
 | |
|                     xmlTextReaderStructuredRelay, reader);
 | |
|         }
 | |
|         if (reader->xsdValidCtxt) {
 | |
|             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
 | |
|                     xmlTextReaderStructuredRelay, reader);
 | |
|         }
 | |
| #endif
 | |
|     } else {
 | |
|         /* restore defaults */
 | |
|         reader->errorFunc = NULL;
 | |
|         reader->sErrorFunc = NULL;
 | |
|         reader->errorFuncArg = NULL;
 | |
|         xmlCtxtSetErrorHandler(reader->ctxt, NULL, NULL);
 | |
| #ifdef LIBXML_SCHEMAS_ENABLED
 | |
|         if (reader->rngValidCtxt) {
 | |
|             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
 | |
|                                                NULL);
 | |
|         }
 | |
|         if (reader->xsdValidCtxt) {
 | |
|             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
 | |
|                                               NULL);
 | |
|         }
 | |
| #endif
 | |
|     }
 | |
| }
 | |
| 
 | |
| /**
 | |
| * xmlTextReaderSetStructuredErrorHandler:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @f:	the callback function to call on error and warnings
 | |
|  * @arg:    a user argument to pass to the callback function
 | |
|  *
 | |
|  * Register a callback function that will be called on error and warnings.
 | |
|  *
 | |
|  * If @f is NULL, the default error and warning handlers are restored.
 | |
|  */
 | |
| void
 | |
| xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
 | |
|                                        xmlStructuredErrorFunc f, void *arg)
 | |
| {
 | |
|     if (f != NULL) {
 | |
|         reader->sErrorFunc = f;
 | |
|         reader->errorFunc = NULL;
 | |
|         reader->errorFuncArg = arg;
 | |
|         xmlCtxtSetErrorHandler(reader->ctxt,
 | |
|                 xmlTextReaderStructuredRelay, reader);
 | |
| #ifdef LIBXML_SCHEMAS_ENABLED
 | |
|         if (reader->rngValidCtxt) {
 | |
|             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
 | |
|                     xmlTextReaderStructuredRelay, reader);
 | |
|         }
 | |
|         if (reader->xsdValidCtxt) {
 | |
|             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
 | |
|                     xmlTextReaderStructuredRelay, reader);
 | |
|         }
 | |
| #endif
 | |
|     } else {
 | |
|         /* restore defaults */
 | |
|         reader->errorFunc = NULL;
 | |
|         reader->sErrorFunc = NULL;
 | |
|         reader->errorFuncArg = NULL;
 | |
|         xmlCtxtSetErrorHandler(reader->ctxt, NULL, NULL);
 | |
| #ifdef LIBXML_SCHEMAS_ENABLED
 | |
|         if (reader->rngValidCtxt) {
 | |
|             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
 | |
|                                                NULL);
 | |
|         }
 | |
|         if (reader->xsdValidCtxt) {
 | |
|             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
 | |
|                                               NULL);
 | |
|         }
 | |
| #endif
 | |
|     }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderGetErrorHandler:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  * @f:	the callback function or NULL is no callback has been registered
 | |
|  * @arg:    a user argument
 | |
|  *
 | |
|  * Retrieve the error callback function and user argument.
 | |
|  */
 | |
| void
 | |
| xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
 | |
|                              xmlTextReaderErrorFunc * f, void **arg)
 | |
| {
 | |
|     if (f != NULL)
 | |
|         *f = reader->errorFunc;
 | |
|     if (arg != NULL)
 | |
|         *arg = reader->errorFuncArg;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderSetResourceLoader:
 | |
|  * @reader:  thr reader
 | |
|  * @loader:  resource loader
 | |
|  * @data:  user data which will be passed to the loader
 | |
|  *
 | |
|  * Register a callback function that will be called to load external
 | |
|  * resources like entities.
 | |
|  *
 | |
|  * Available since 2.14.0.
 | |
|  */
 | |
| void
 | |
| xmlTextReaderSetResourceLoader(xmlTextReaderPtr reader,
 | |
|                                xmlResourceLoader loader, void *data) {
 | |
|     if ((reader == NULL) || (reader->ctxt == NULL))
 | |
|         return;
 | |
| 
 | |
|     reader->resourceLoader = loader;
 | |
|     reader->resourceCtxt = data;
 | |
| 
 | |
|     xmlCtxtSetResourceLoader(reader->ctxt, loader, data);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderIsValid:
 | |
|  * @reader:  the xmlTextReaderPtr used
 | |
|  *
 | |
|  * Retrieve the validity status from the parser context
 | |
|  *
 | |
|  * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
 | |
|  */
 | |
| int
 | |
| xmlTextReaderIsValid(xmlTextReaderPtr reader)
 | |
| {
 | |
|     if (reader == NULL)
 | |
|         return (-1);
 | |
| #ifdef LIBXML_SCHEMAS_ENABLED
 | |
|     if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
 | |
|         return (reader->rngValidErrors == 0);
 | |
|     if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
 | |
|         return (reader->xsdValidErrors == 0);
 | |
| #endif
 | |
|     if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
 | |
|         return (reader->ctxt->valid);
 | |
|     return (0);
 | |
| }
 | |
| 
 | |
| /************************************************************************
 | |
|  *									*
 | |
|  *	New set (2.6.0) of simpler and more flexible APIs		*
 | |
|  *									*
 | |
|  ************************************************************************/
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderSetup:
 | |
|  * @reader:  an XML reader
 | |
|  * @input: xmlParserInputBufferPtr used to feed the reader, will
 | |
|  *         be destroyed with it.
 | |
|  * @URL:  the base URL to use for the document
 | |
|  * @encoding:  the document encoding, or NULL
 | |
|  * @options:  a combination of xmlParserOption
 | |
|  *
 | |
|  * Setup an XML reader with new options
 | |
|  *
 | |
|  * Returns 0 in case of success and -1 in case of error.
 | |
|  */
 | |
| int
 | |
| xmlTextReaderSetup(xmlTextReaderPtr reader,
 | |
|                    xmlParserInputBufferPtr input, const char *URL,
 | |
|                    const char *encoding, int options)
 | |
| {
 | |
|     if (reader == NULL) {
 | |
|         if (input != NULL)
 | |
| 	    xmlFreeParserInputBuffer(input);
 | |
|         return (-1);
 | |
|     }
 | |
| 
 | |
|     /*
 | |
|      * we force the generation of compact text nodes on the reader
 | |
|      * since usr applications should never modify the tree
 | |
|      */
 | |
|     options |= XML_PARSE_COMPACT;
 | |
| 
 | |
|     reader->doc = NULL;
 | |
|     reader->entNr = 0;
 | |
|     reader->parserFlags = options;
 | |
|     reader->validate = XML_TEXTREADER_NOT_VALIDATE;
 | |
|     if ((input != NULL) && (reader->input != NULL) &&
 | |
|         (reader->allocs & XML_TEXTREADER_INPUT)) {
 | |
| 	xmlFreeParserInputBuffer(reader->input);
 | |
| 	reader->input = NULL;
 | |
| 	reader->allocs -= XML_TEXTREADER_INPUT;
 | |
|     }
 | |
|     if (input != NULL) {
 | |
| 	reader->input = input;
 | |
| 	reader->allocs |= XML_TEXTREADER_INPUT;
 | |
|     }
 | |
|     if (reader->buffer == NULL)
 | |
|         reader->buffer = xmlBufCreate(50);
 | |
|     if (reader->buffer == NULL) {
 | |
|         return (-1);
 | |
|     }
 | |
|     if (reader->sax == NULL)
 | |
| 	reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
 | |
|     if (reader->sax == NULL) {
 | |
|         return (-1);
 | |
|     }
 | |
|     xmlSAXVersion(reader->sax, 2);
 | |
|     reader->startElement = reader->sax->startElement;
 | |
|     reader->sax->startElement = xmlTextReaderStartElement;
 | |
|     reader->endElement = reader->sax->endElement;
 | |
|     reader->sax->endElement = xmlTextReaderEndElement;
 | |
| #ifdef LIBXML_SAX1_ENABLED
 | |
|     if (reader->sax->initialized == XML_SAX2_MAGIC) {
 | |
| #endif /* LIBXML_SAX1_ENABLED */
 | |
|         reader->startElementNs = reader->sax->startElementNs;
 | |
|         reader->sax->startElementNs = xmlTextReaderStartElementNs;
 | |
|         reader->endElementNs = reader->sax->endElementNs;
 | |
|         reader->sax->endElementNs = xmlTextReaderEndElementNs;
 | |
| #ifdef LIBXML_SAX1_ENABLED
 | |
|     } else {
 | |
|         reader->startElementNs = NULL;
 | |
|         reader->endElementNs = NULL;
 | |
|     }
 | |
| #endif /* LIBXML_SAX1_ENABLED */
 | |
|     reader->characters = reader->sax->characters;
 | |
|     reader->sax->characters = xmlTextReaderCharacters;
 | |
|     reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
 | |
|     reader->cdataBlock = reader->sax->cdataBlock;
 | |
|     reader->sax->cdataBlock = xmlTextReaderCDataBlock;
 | |
| 
 | |
|     reader->mode = XML_TEXTREADER_MODE_INITIAL;
 | |
|     reader->node = NULL;
 | |
|     reader->curnode = NULL;
 | |
|     if (input != NULL) {
 | |
|         if (xmlBufUse(reader->input->buffer) < 4) {
 | |
|             xmlParserInputBufferRead(input, 4);
 | |
|         }
 | |
|         if (reader->ctxt == NULL) {
 | |
|             if (xmlBufUse(reader->input->buffer) >= 4) {
 | |
|                 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
 | |
| 		       (const char *) xmlBufContent(reader->input->buffer),
 | |
|                                       4, URL);
 | |
|                 reader->base = 0;
 | |
|                 reader->cur = 4;
 | |
|             } else {
 | |
|                 reader->ctxt =
 | |
|                     xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
 | |
|                 reader->base = 0;
 | |
|                 reader->cur = 0;
 | |
|             }
 | |
|             if (reader->ctxt == NULL) {
 | |
|                 return (-1);
 | |
|             }
 | |
|         } else {
 | |
| 	    xmlParserInputPtr inputStream;
 | |
| 	    xmlParserInputBufferPtr buf;
 | |
| 
 | |
| 	    xmlCtxtReset(reader->ctxt);
 | |
| 	    buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE);
 | |
| 	    if (buf == NULL) return(-1);
 | |
| 	    inputStream = xmlNewInputStream(reader->ctxt);
 | |
| 	    if (inputStream == NULL) {
 | |
| 		xmlFreeParserInputBuffer(buf);
 | |
| 		return(-1);
 | |
| 	    }
 | |
| 
 | |
| 	    if (URL == NULL)
 | |
| 		inputStream->filename = NULL;
 | |
| 	    else
 | |
| 		inputStream->filename = (char *)
 | |
| 		    xmlCanonicPath((const xmlChar *) URL);
 | |
| 	    inputStream->buf = buf;
 | |
|             xmlBufResetInput(buf->buffer, inputStream);
 | |
| 
 | |
|             if (inputPush(reader->ctxt, inputStream) < 0) {
 | |
|                 xmlFreeInputStream(inputStream);
 | |
|                 return(-1);
 | |
|             }
 | |
| 	    reader->cur = 0;
 | |
| 	}
 | |
|     }
 | |
|     if (reader->dict != NULL) {
 | |
|         if (reader->ctxt->dict != NULL) {
 | |
| 	    if (reader->dict != reader->ctxt->dict) {
 | |
| 		xmlDictFree(reader->dict);
 | |
| 		reader->dict = reader->ctxt->dict;
 | |
| 	    }
 | |
| 	} else {
 | |
| 	    reader->ctxt->dict = reader->dict;
 | |
| 	}
 | |
|     } else {
 | |
| 	if (reader->ctxt->dict == NULL)
 | |
| 	    reader->ctxt->dict = xmlDictCreate();
 | |
|         reader->dict = reader->ctxt->dict;
 | |
|     }
 | |
|     reader->ctxt->_private = reader;
 | |
|     reader->ctxt->linenumbers = 1;
 | |
|     reader->ctxt->dictNames = 1;
 | |
|     /*
 | |
|      * use the parser dictionary to allocate all elements and attributes names
 | |
|      */
 | |
|     reader->ctxt->parseMode = XML_PARSE_READER;
 | |
| 
 | |
| #ifdef LIBXML_XINCLUDE_ENABLED
 | |
|     if (reader->xincctxt != NULL) {
 | |
| 	xmlXIncludeFreeContext(reader->xincctxt);
 | |
| 	reader->xincctxt = NULL;
 | |
|     }
 | |
|     if (options & XML_PARSE_XINCLUDE) {
 | |
|         reader->xinclude = 1;
 | |
| 	reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
 | |
|         if (reader->xinclude_name == NULL)
 | |
|             return(-1);
 | |
| 	options -= XML_PARSE_XINCLUDE;
 | |
|     } else
 | |
|         reader->xinclude = 0;
 | |
|     reader->in_xinclude = 0;
 | |
| #endif
 | |
| #ifdef LIBXML_PATTERN_ENABLED
 | |
|     if (reader->patternTab == NULL) {
 | |
|         reader->patternNr = 0;
 | |
| 	reader->patternMax = 0;
 | |
|     }
 | |
|     while (reader->patternNr > 0) {
 | |
|         reader->patternNr--;
 | |
| 	if (reader->patternTab[reader->patternNr] != NULL) {
 | |
| 	    xmlFreePattern(reader->patternTab[reader->patternNr]);
 | |
|             reader->patternTab[reader->patternNr] = NULL;
 | |
| 	}
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     if (options & XML_PARSE_DTDVALID)
 | |
|         reader->validate = XML_TEXTREADER_VALIDATE_DTD;
 | |
| 
 | |
|     xmlCtxtUseOptions(reader->ctxt, options);
 | |
|     if (encoding != NULL)
 | |
|         xmlSwitchEncodingName(reader->ctxt, encoding);
 | |
|     if ((URL != NULL) && (reader->ctxt->input != NULL) &&
 | |
|         (reader->ctxt->input->filename == NULL)) {
 | |
|         reader->ctxt->input->filename = (char *)
 | |
|             xmlStrdup((const xmlChar *) URL);
 | |
|         if (reader->ctxt->input->filename == NULL)
 | |
|             return(-1);
 | |
|     }
 | |
| 
 | |
|     reader->doc = NULL;
 | |
| 
 | |
|     return (0);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderSetMaxAmplification:
 | |
|  * @reader: an XML reader
 | |
|  * @maxAmpl:  maximum amplification factor
 | |
|  *
 | |
|  * Set the maximum amplification factor. See xmlCtxtSetMaxAmplification.
 | |
|  */
 | |
| void
 | |
| xmlTextReaderSetMaxAmplification(xmlTextReaderPtr reader, unsigned maxAmpl)
 | |
| {
 | |
|     xmlCtxtSetMaxAmplification(reader->ctxt, maxAmpl);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderGetLastError:
 | |
|  * @reader: an XML reader
 | |
|  *
 | |
|  * Available since 2.13.0.
 | |
|  *
 | |
|  * Returns the last error.
 | |
|  */
 | |
| const xmlError *
 | |
| xmlTextReaderGetLastError(xmlTextReaderPtr reader)
 | |
| {
 | |
|     if (reader == NULL)
 | |
|         return(NULL);
 | |
|     return(&reader->ctxt->lastError);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlTextReaderByteConsumed:
 | |
|  * @reader: an XML reader
 | |
|  *
 | |
|  * DEPRECATED: The returned value is mostly random and useless.
 | |
|  * It reflects the parser reading ahead and is in no way related to
 | |
|  * the current node.
 | |
|  *
 | |
|  * This function provides the current index of the parser used
 | |
|  * by the reader, relative to the start of the current entity.
 | |
|  * This function actually just wraps a call to xmlBytesConsumed()
 | |
|  * for the parser context associated with the reader.
 | |
|  * See xmlBytesConsumed() for more information.
 | |
|  *
 | |
|  * Returns the index in bytes from the beginning of the entity or -1
 | |
|  *         in case the index could not be computed.
 | |
|  */
 | |
| long
 | |
| xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
 | |
|     xmlParserInputPtr in;
 | |
| 
 | |
|     if ((reader == NULL) || (reader->ctxt == NULL))
 | |
|         return(-1);
 | |
|     in = reader->ctxt->input;
 | |
|     if (in == NULL)
 | |
|         return(-1);
 | |
|     return(in->consumed + (in->cur - in->base));
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * xmlReaderWalker:
 | |
|  * @doc:  a preparsed document
 | |
|  *
 | |
|  * Create an xmltextReader for a preparsed document.
 | |
|  *
 | |
|  * Returns the new reader or NULL in case of error.
 | |
|  */
 | |
| xmlTextReaderPtr
 | |
| xmlReaderWalker(xmlDocPtr doc)
 | |
| {
 | |
|     xmlTextReaderPtr ret;
 | |
| 
 | |
|     if (doc == NULL)
 | |
|         return(NULL);
 | |
| 
 | |
|     ret = xmlMalloc(sizeof(xmlTextReader));
 | |
|     if (ret == NULL) {
 | |
| 	return(NULL);
 | |
|     }
 | |
|     memset(ret, 0, sizeof(xmlTextReader));
 | |
|     ret->entNr = 0;
 | |
|     ret->input = NULL;
 | |
|     ret->mode = XML_TEXTREADER_MODE_INITIAL;
 | |
|     ret->node = NULL;
 | |
|     ret->curnode = NULL;
 | |
|     ret->base = 0;
 | |
|     ret->cur = 0;
 | |
|     ret->allocs = XML_TEXTREADER_CTXT;
 | |
|     ret->doc = doc;
 | |
|     ret->state = XML_TEXTREADER_START;
 | |
|     ret->dict = xmlDictCreate();
 | |
|     return(ret);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlReaderForDoc:
 | |
|  * @cur:  a pointer to a zero terminated string
 | |
|  * @URL:  the base URL to use for the document
 | |
|  * @encoding:  the document encoding, or NULL
 | |
|  * @options:  a combination of xmlParserOption
 | |
|  *
 | |
|  * Create an xmltextReader for an XML in-memory document.
 | |
|  * The parsing flags @options are a combination of xmlParserOption.
 | |
|  *
 | |
|  * Returns the new reader or NULL in case of error.
 | |
|  */
 | |
| xmlTextReaderPtr
 | |
| xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
 | |
|                 int options)
 | |
| {
 | |
|     int len;
 | |
| 
 | |
|     if (cur == NULL)
 | |
|         return (NULL);
 | |
|     len = xmlStrlen(cur);
 | |
| 
 | |
|     return (xmlReaderForMemory
 | |
|             ((const char *) cur, len, URL, encoding, options));
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlReaderForFile:
 | |
|  * @filename:  a file or URL
 | |
|  * @encoding:  the document encoding, or NULL
 | |
|  * @options:  a combination of xmlParserOption
 | |
|  *
 | |
|  * parse an XML file from the filesystem or the network.
 | |
|  * The parsing flags @options are a combination of xmlParserOption.
 | |
|  *
 | |
|  * Returns the new reader or NULL in case of error.
 | |
|  */
 | |
| xmlTextReaderPtr
 | |
| xmlReaderForFile(const char *filename, const char *encoding, int options)
 | |
| {
 | |
|     xmlTextReaderPtr reader;
 | |
| 
 | |
|     reader = xmlNewTextReaderFilename(filename);
 | |
|     if (reader == NULL)
 | |
|         return (NULL);
 | |
|     if (xmlTextReaderSetup(reader, NULL, NULL, encoding, options) < 0) {
 | |
|         xmlFreeTextReader(reader);
 | |
|         return (NULL);
 | |
|     }
 | |
|     return (reader);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlReaderForMemory:
 | |
|  * @buffer:  a pointer to a char array
 | |
|  * @size:  the size of the array
 | |
|  * @URL:  the base URL to use for the document
 | |
|  * @encoding:  the document encoding, or NULL
 | |
|  * @options:  a combination of xmlParserOption
 | |
|  *
 | |
|  * Create an xmltextReader for an XML in-memory document.
 | |
|  * The parsing flags @options are a combination of xmlParserOption.
 | |
|  *
 | |
|  * Returns the new reader or NULL in case of error.
 | |
|  */
 | |
| xmlTextReaderPtr
 | |
| xmlReaderForMemory(const char *buffer, int size, const char *URL,
 | |
|                    const char *encoding, int options)
 | |
| {
 | |
|     xmlTextReaderPtr reader;
 | |
|     xmlParserInputBufferPtr buf;
 | |
| 
 | |
|     buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
 | |
|     if (buf == NULL) {
 | |
|         return (NULL);
 | |
|     }
 | |
|     reader = xmlNewTextReader(buf, URL);
 | |
|     if (reader == NULL) {
 | |
|         xmlFreeParserInputBuffer(buf);
 | |
|         return (NULL);
 | |
|     }
 | |
|     reader->allocs |= XML_TEXTREADER_INPUT;
 | |
|     if (xmlTextReaderSetup(reader, NULL, URL, encoding, options) < 0) {
 | |
|         xmlFreeTextReader(reader);
 | |
|         return (NULL);
 | |
|     }
 | |
|     return (reader);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlReaderForFd:
 | |
|  * @fd:  an open file descriptor
 | |
|  * @URL:  the base URL to use for the document
 | |
|  * @encoding:  the document encoding, or NULL
 | |
|  * @options:  a combination of xmlParserOption
 | |
|  *
 | |
|  * Create an xmltextReader for an XML from a file descriptor.
 | |
|  * The parsing flags @options are a combination of xmlParserOption.
 | |
|  * NOTE that the file descriptor will not be closed when the
 | |
|  *      reader is closed or reset.
 | |
|  *
 | |
|  * Returns the new reader or NULL in case of error.
 | |
|  */
 | |
| xmlTextReaderPtr
 | |
| xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
 | |
| {
 | |
|     xmlTextReaderPtr reader;
 | |
|     xmlParserInputBufferPtr input;
 | |
| 
 | |
|     if (fd < 0)
 | |
|         return (NULL);
 | |
| 
 | |
|     input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
 | |
|     if (input == NULL)
 | |
|         return (NULL);
 | |
|     input->closecallback = NULL;
 | |
|     reader = xmlNewTextReader(input, URL);
 | |
|     if (reader == NULL) {
 | |
|         xmlFreeParserInputBuffer(input);
 | |
|         return (NULL);
 | |
|     }
 | |
|     reader->allocs |= XML_TEXTREADER_INPUT;
 | |
|     if (xmlTextReaderSetup(reader, NULL, URL, encoding, options) < 0) {
 | |
|         xmlFreeTextReader(reader);
 | |
|         return (NULL);
 | |
|     }
 | |
|     return (reader);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlReaderForIO:
 | |
|  * @ioread:  an I/O read function
 | |
|  * @ioclose:  an I/O close function
 | |
|  * @ioctx:  an I/O handler
 | |
|  * @URL:  the base URL to use for the document
 | |
|  * @encoding:  the document encoding, or NULL
 | |
|  * @options:  a combination of xmlParserOption
 | |
|  *
 | |
|  * Create an xmltextReader for an XML document from I/O functions and source.
 | |
|  * The parsing flags @options are a combination of xmlParserOption.
 | |
|  *
 | |
|  * Returns the new reader or NULL in case of error.
 | |
|  */
 | |
| xmlTextReaderPtr
 | |
| xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
 | |
|                void *ioctx, const char *URL, const char *encoding,
 | |
|                int options)
 | |
| {
 | |
|     xmlTextReaderPtr reader;
 | |
|     xmlParserInputBufferPtr input;
 | |
| 
 | |
|     if (ioread == NULL)
 | |
|         return (NULL);
 | |
| 
 | |
|     input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
 | |
|                                          XML_CHAR_ENCODING_NONE);
 | |
|     if (input == NULL) {
 | |
|         if (ioclose != NULL)
 | |
|             ioclose(ioctx);
 | |
|         return (NULL);
 | |
|     }
 | |
|     reader = xmlNewTextReader(input, URL);
 | |
|     if (reader == NULL) {
 | |
|         xmlFreeParserInputBuffer(input);
 | |
|         return (NULL);
 | |
|     }
 | |
|     reader->allocs |= XML_TEXTREADER_INPUT;
 | |
|     if (xmlTextReaderSetup(reader, NULL, URL, encoding, options) < 0) {
 | |
|         xmlFreeTextReader(reader);
 | |
|         return (NULL);
 | |
|     }
 | |
|     return (reader);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlReaderNewWalker:
 | |
|  * @reader:  an XML reader
 | |
|  * @doc:  a preparsed document
 | |
|  *
 | |
|  * Setup an xmltextReader to parse a preparsed XML document.
 | |
|  * This reuses the existing @reader xmlTextReader.
 | |
|  *
 | |
|  * Returns 0 in case of success and -1 in case of error
 | |
|  */
 | |
| int
 | |
| xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
 | |
| {
 | |
|     if (doc == NULL)
 | |
|         return (-1);
 | |
|     if (reader == NULL)
 | |
|         return (-1);
 | |
| 
 | |
|     if (reader->input != NULL) {
 | |
|         xmlFreeParserInputBuffer(reader->input);
 | |
|     }
 | |
|     if (reader->ctxt != NULL) {
 | |
| 	xmlCtxtReset(reader->ctxt);
 | |
|     }
 | |
| 
 | |
|     reader->entNr = 0;
 | |
|     reader->input = NULL;
 | |
|     reader->mode = XML_TEXTREADER_MODE_INITIAL;
 | |
|     reader->node = NULL;
 | |
|     reader->curnode = NULL;
 | |
|     reader->base = 0;
 | |
|     reader->cur = 0;
 | |
|     reader->allocs = XML_TEXTREADER_CTXT;
 | |
|     reader->doc = doc;
 | |
|     reader->state = XML_TEXTREADER_START;
 | |
|     if (reader->dict == NULL) {
 | |
|         if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
 | |
| 	    reader->dict = reader->ctxt->dict;
 | |
| 	else
 | |
| 	    reader->dict = xmlDictCreate();
 | |
|     }
 | |
|     return(0);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlReaderNewDoc:
 | |
|  * @reader:  an XML reader
 | |
|  * @cur:  a pointer to a zero terminated string
 | |
|  * @URL:  the base URL to use for the document
 | |
|  * @encoding:  the document encoding, or NULL
 | |
|  * @options:  a combination of xmlParserOption
 | |
|  *
 | |
|  * Setup an xmltextReader to parse an XML in-memory document.
 | |
|  * The parsing flags @options are a combination of xmlParserOption.
 | |
|  * This reuses the existing @reader xmlTextReader.
 | |
|  *
 | |
|  * Returns 0 in case of success and -1 in case of error
 | |
|  */
 | |
| int
 | |
| xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
 | |
|                 const char *URL, const char *encoding, int options)
 | |
| {
 | |
| 
 | |
|     int len;
 | |
| 
 | |
|     if (cur == NULL)
 | |
|         return (-1);
 | |
|     if (reader == NULL)
 | |
|         return (-1);
 | |
| 
 | |
|     len = xmlStrlen(cur);
 | |
|     return (xmlReaderNewMemory(reader, (const char *)cur, len,
 | |
|                                URL, encoding, options));
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlReaderNewFile:
 | |
|  * @reader:  an XML reader
 | |
|  * @filename:  a file or URL
 | |
|  * @encoding:  the document encoding, or NULL
 | |
|  * @options:  a combination of xmlParserOption
 | |
|  *
 | |
|  * parse an XML file from the filesystem or the network.
 | |
|  * The parsing flags @options are a combination of xmlParserOption.
 | |
|  * This reuses the existing @reader xmlTextReader.
 | |
|  *
 | |
|  * Returns 0 in case of success and -1 in case of error
 | |
|  */
 | |
| int
 | |
| xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
 | |
|                  const char *encoding, int options)
 | |
| {
 | |
|     xmlParserInputBufferPtr input;
 | |
| 
 | |
|     if (filename == NULL)
 | |
|         return (-1);
 | |
|     if (reader == NULL)
 | |
|         return (-1);
 | |
| 
 | |
|     input =
 | |
|         xmlParserInputBufferCreateFilename(filename,
 | |
|                                            XML_CHAR_ENCODING_NONE);
 | |
|     if (input == NULL)
 | |
|         return (-1);
 | |
|     return (xmlTextReaderSetup(reader, input, filename, encoding, options));
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlReaderNewMemory:
 | |
|  * @reader:  an XML reader
 | |
|  * @buffer:  a pointer to a char array
 | |
|  * @size:  the size of the array
 | |
|  * @URL:  the base URL to use for the document
 | |
|  * @encoding:  the document encoding, or NULL
 | |
|  * @options:  a combination of xmlParserOption
 | |
|  *
 | |
|  * Setup an xmltextReader to parse an XML in-memory document.
 | |
|  * The parsing flags @options are a combination of xmlParserOption.
 | |
|  * This reuses the existing @reader xmlTextReader.
 | |
|  *
 | |
|  * Returns 0 in case of success and -1 in case of error
 | |
|  */
 | |
| int
 | |
| xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
 | |
|                    const char *URL, const char *encoding, int options)
 | |
| {
 | |
|     xmlParserInputBufferPtr input;
 | |
| 
 | |
|     if (reader == NULL)
 | |
|         return (-1);
 | |
|     if (buffer == NULL)
 | |
|         return (-1);
 | |
| 
 | |
|     input = xmlParserInputBufferCreateMem(buffer, size,
 | |
|                                       XML_CHAR_ENCODING_NONE);
 | |
|     if (input == NULL) {
 | |
|         return (-1);
 | |
|     }
 | |
|     return (xmlTextReaderSetup(reader, input, URL, encoding, options));
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlReaderNewFd:
 | |
|  * @reader:  an XML reader
 | |
|  * @fd:  an open file descriptor
 | |
|  * @URL:  the base URL to use for the document
 | |
|  * @encoding:  the document encoding, or NULL
 | |
|  * @options:  a combination of xmlParserOption
 | |
|  *
 | |
|  * Setup an xmltextReader to parse an XML from a file descriptor.
 | |
|  * NOTE that the file descriptor will not be closed when the
 | |
|  *      reader is closed or reset.
 | |
|  * The parsing flags @options are a combination of xmlParserOption.
 | |
|  * This reuses the existing @reader xmlTextReader.
 | |
|  *
 | |
|  * Returns 0 in case of success and -1 in case of error
 | |
|  */
 | |
| int
 | |
| xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
 | |
|                const char *URL, const char *encoding, int options)
 | |
| {
 | |
|     xmlParserInputBufferPtr input;
 | |
| 
 | |
|     if (fd < 0)
 | |
|         return (-1);
 | |
|     if (reader == NULL)
 | |
|         return (-1);
 | |
| 
 | |
|     input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
 | |
|     if (input == NULL)
 | |
|         return (-1);
 | |
|     input->closecallback = NULL;
 | |
|     return (xmlTextReaderSetup(reader, input, URL, encoding, options));
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * xmlReaderNewIO:
 | |
|  * @reader:  an XML reader
 | |
|  * @ioread:  an I/O read function
 | |
|  * @ioclose:  an I/O close function
 | |
|  * @ioctx:  an I/O handler
 | |
|  * @URL:  the base URL to use for the document
 | |
|  * @encoding:  the document encoding, or NULL
 | |
|  * @options:  a combination of xmlParserOption
 | |
|  *
 | |
|  * Setup an xmltextReader to parse an XML document from I/O functions
 | |
|  * and source.
 | |
|  * The parsing flags @options are a combination of xmlParserOption.
 | |
|  * This reuses the existing @reader xmlTextReader.
 | |
|  *
 | |
|  * Returns 0 in case of success and -1 in case of error
 | |
|  */
 | |
| int
 | |
| xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
 | |
|                xmlInputCloseCallback ioclose, void *ioctx,
 | |
|                const char *URL, const char *encoding, int options)
 | |
| {
 | |
|     xmlParserInputBufferPtr input;
 | |
| 
 | |
|     if (ioread == NULL)
 | |
|         return (-1);
 | |
|     if (reader == NULL)
 | |
|         return (-1);
 | |
| 
 | |
|     input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
 | |
|                                          XML_CHAR_ENCODING_NONE);
 | |
|     if (input == NULL) {
 | |
|         if (ioclose != NULL)
 | |
|             ioclose(ioctx);
 | |
|         return (-1);
 | |
|     }
 | |
|     return (xmlTextReaderSetup(reader, input, URL, encoding, options));
 | |
| }
 | |
| 
 | |
| #endif /* LIBXML_READER_ENABLED */
 |