DriveHQ Start Menu
Cloud Drive Mapping
Folder Sync
Cloud Backup
True Drop Box
FTP/SFTP Hosting
Group Account
DriveHQ Start Menu
Online File Server
My Storage
|
Manage Shares
|
Publishes
|
Drop Boxes
|
Group Account
WebDAV Drive Mapping
Cloud Drive Home
|
WebDAV Guide
|
Drive Mapping Tool
|
Drive Mapping URL
Complete Data Backup
Backup Guide
|
Online Backup Tool
|
Cloud-to-Cloud Backup
FTP, Email & Web Service
FTP Home
|
FTP Hosting FAQ
|
Email Hosting
|
EmailManager
|
Web Hosting
Help & Resources
About
|
Enterprise Service
|
Partnership
|
Comparisons
|
Support
Quick Links
Security and Privacy
Download Software
Service Manual
Use Cases
Group Account
Online Help
Blog
Contact
Cloud Surveillance
Sign Up
Login
Features
Business Features
Online File Server
FTP Hosting
Cloud Drive Mapping
Cloud File Backup
Email Backup & Hosting
Cloud File Sharing
Folder Synchronization
Group Management
True Drop Box
Full-text Search
AD Integration/SSO
Mobile Access
IP Camera & DVR Solution
More...
Personal Features
Personal Cloud Drive
Backup All Devices
Mobile APPs
Personal Web Hosting
Sub-Account (for Kids)
Home/PC/Kids Monitoring
More...
Software
DriveHQ Drive Mapping Tool
DriveHQ FileManager
DriveHQ Online Backup
DriveHQ Mobile Apps
Pricing
Business Plans & Pricing
Personal Plans & Pricing
Price Comparison with Others
Feature Comparison with Others
Install Mobile App
Sign up
Creating account...
Invalid character in username! Only 0-9, a-z, A-Z, _, -, . allowed.
Username is required!
Invalid email address!
E-mail is required!
Password is required!
Password is invalid!
Password and confirmation do not match.
Confirm password is required!
I accept
Membership Agreement
Please read the Membership Agreement and check "I accept"!
Free Quick Sign-up
Sign-up Page
Log in
Signing in...
Username or e-mail address is required!
Password is required!
Keep me logged in
Quick Login
Forgot Password
Up
Upload
Download
Share
Publish
New Folder
New File
Copy
Cut
Delete
Paste
Rate
Upgrade
Rotate
Effect
Edit
Slide
History
/* * 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
/* for memset() only ! */ #include
#ifdef HAVE_CTYPE_H #include
#endif #ifdef HAVE_STDLIB_H #include
#endif #include
#include
#include
#include
#ifdef LIBXML_SCHEMAS_ENABLED #include
#include
#endif #include
#ifdef LIBXML_XINCLUDE_ENABLED #include
#endif #ifdef LIBXML_PATTERN_ENABLED #include
#endif /* #define DEBUG_CALLBACKS */ /* #define DEBUG_READER */ /** * TODO: * * macro to flag unimplemented blocks */ #define TODO \ xmlGenericError(xmlGenericErrorContext, \ "Unimplemented block at %s:%d\n", \ __FILE__, __LINE__); #ifdef DEBUG_READER #define DUMP_READER xmlTextReaderDebug(reader); #else #define DUMP_READER #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 */ xmlBufferPtr buffer; /* used to return const xmlChar * */ xmlDictPtr dict; /* the context dictionnary */ /* 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 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 */ }; #define NODE_IS_EMPTY 0x1 #define NODE_IS_PRESERVED 0x2 #define NODE_IS_SPRESERVED 0x4 /** * CONSTSTR: * * Macro used to return an interned string */ #define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1) #define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str)) static int xmlTextReaderReadTree(xmlTextReaderPtr reader); static int xmlTextReaderNextTree(xmlTextReaderPtr reader); /************************************************************************ * * * Our own version of the freeing routines as we recycle nodes * * * ************************************************************************/ /** * DICT_FREE: * @str: a string * * Free a string if it is not owned by the "dict" dictionnary 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); /** * xmlFreeID: * @not: A id * * Deallocate the memory used by an id definition */ static void xmlFreeID(xmlIDPtr id) { xmlDictPtr dict = NULL; if (id == NULL) return; if (id->doc != NULL) dict = id->doc->dict; if (id->value != NULL) DICT_FREE(id->value) xmlFree(id); } /** * xmlTextReaderRemoveID: * @doc: the document * @attr: the attribute * * Remove the given attribute from the ID table maintained internally. * * Returns -1 if the lookup failed and 0 otherwise */ static int xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) { xmlIDTablePtr table; xmlIDPtr id; xmlChar *ID; if (doc == NULL) return(-1); if (attr == NULL) return(-1); table = (xmlIDTablePtr) doc->ids; if (table == NULL) return(-1); if (attr == NULL) return(-1); ID = xmlNodeListGetString(doc, attr->children, 1); if (ID == NULL) return(-1); id = xmlHashLookup(table, ID); xmlFree(ID); if (id == NULL || id->attr != attr) { return(-1); } id->name = attr->name; id->attr = NULL; return(0); } /** * xmlTextReaderFreeProp: * @reader: the xmlTextReaderPtr used * @cur: the node * * Free a node. */ static void xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) { xmlDictPtr dict; dict = reader->ctxt->dict; if (cur == NULL) return; if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) xmlDeregisterNodeDefaultValue((xmlNodePtr) cur); /* Check for ID removal -> leading to invalid references ! */ if ((cur->parent != NULL) && (cur->parent->doc != NULL) && ((cur->parent->doc->intSubset != NULL) || (cur->parent->doc->extSubset != NULL))) { if (xmlIsID(cur->parent->doc, cur->parent, cur)) xmlTextReaderRemoveID(cur->parent->doc, cur); } if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children); DICT_FREE(cur->name); if ((reader != NULL) && (reader->ctxt != NULL) && (reader->ctxt->freeAttrsNr < 100)) { 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; if (cur == NULL) return; 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; xmlDictPtr dict; dict = reader->ctxt->dict; 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 (cur != NULL) { next = cur->next; /* unroll to speed up freeing the document */ if (cur->type != XML_DTD_NODE) { 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 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 < 100)) { cur->next = reader->ctxt->freeElems; reader->ctxt->freeElems = cur; reader->ctxt->freeElemsNr++; } else { xmlFree(cur); } } cur = next; } } /** * 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; dict = reader->ctxt->dict; 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 < 100)) { cur->next = reader->ctxt->freeElems; reader->ctxt->freeElems = cur; reader->ctxt->freeElemsNr++; } else { xmlFree(cur); } } /** * xmlTextReaderFreeIDTable: * @table: An id table * * Deallocate the memory used by an ID hash table. */ static void xmlTextReaderFreeIDTable(xmlIDTablePtr table) { xmlHashFree(table, (xmlHashDeallocator) xmlFreeID); } /** * 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) xmlTextReaderFreeIDTable((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 * * * ************************************************************************/ #ifdef DEBUG_READER static void xmlTextReaderDebug(xmlTextReaderPtr reader) { if ((reader == NULL) || (reader->ctxt == NULL)) { fprintf(stderr, "xmlTextReader NULL\n"); return; } fprintf(stderr, "xmlTextReader: state %d depth %d ", reader->state, reader->depth); if (reader->node == NULL) { fprintf(stderr, "node = NULL\n"); } else { fprintf(stderr, "node %s\n", reader->node->name); } fprintf(stderr, " input: base %d, cur %d, depth %d: ", reader->base, reader->cur, reader->ctxt->nodeNr); if (reader->input->buffer == NULL) { fprintf(stderr, "buffer is NULL\n"); } else { #ifdef LIBXML_DEBUG_ENABLED xmlDebugDumpString(stderr, &reader->input->buffer->content[reader->cur]); #endif fprintf(stderr, "\n"); } } #endif /** * xmlTextReaderEntPush: * @reader: the xmlTextReaderPtr used * @value: the entity reference node * * Pushes a new entity reference node on top of the entities stack * * Returns 0 in case of error, the index in the stack otherwise */ static int xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value) { if (reader->entMax <= 0) { reader->entMax = 10; reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax * sizeof(reader->entTab[0])); if (reader->entTab == NULL) { xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n"); return (0); } } if (reader->entNr >= reader->entMax) { reader->entMax *= 2; reader->entTab = (xmlNodePtr *) xmlRealloc(reader->entTab, reader->entMax * sizeof(reader->entTab[0])); if (reader->entTab == NULL) { xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n"); return (0); } } 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; #ifdef DEBUG_CALLBACKS printf("xmlTextReaderStartElement(%s)\n", fullname); #endif 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; #ifdef DEBUG_CALLBACKS printf("xmlTextReaderEndElement(%s)\n", fullname); #endif 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; #ifdef DEBUG_CALLBACKS printf("xmlTextReaderStartElementNs(%s)\n", localname); #endif 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; #ifdef DEBUG_CALLBACKS printf("xmlTextReaderEndElementNs(%s)\n", localname); #endif 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; #ifdef DEBUG_CALLBACKS printf("xmlTextReaderCharacters()\n"); #endif 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; #ifdef DEBUG_CALLBACKS printf("xmlTextReaderCDataBlock()\n"); #endif 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) { xmlBufferPtr 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 (inbuf->use < 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) && (inbuf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) { if (inbuf->use == reader->cur) { reader->mode = XML_TEXTREADER_MODE_EOF; reader->state = oldstate; } } else if (val < 0) { reader->mode = XML_TEXTREADER_MODE_EOF; reader->state = oldstate; if ((oldstate != XML_TEXTREADER_START) || (reader->ctxt->myDoc != NULL)) return(val); } else if (val == 0) { /* mark the end of the stream and process the remains */ reader->mode = XML_TEXTREADER_MODE_EOF; break; } } 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 (inbuf->use >= reader->cur + CHUNK_SIZE) { val = xmlParseChunk(reader->ctxt, (const char *) &inbuf->content[reader->cur], CHUNK_SIZE, 0); reader->cur += CHUNK_SIZE; if ((val != 0) || (reader->ctxt->wellFormed == 0)) return(-1); } else { s = inbuf->use - reader->cur; val = xmlParseChunk(reader->ctxt, (const char *) &inbuf->content[reader->cur], s, 0); reader->cur += s; if ((val != 0) || (reader->ctxt->wellFormed == 0)) return(-1); break; } } /* * Discard the consumed input when needed and possible */ if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) { if (inbuf->alloc != XML_BUFFER_ALLOC_IMMUTABLE) { if ((reader->cur >= 4096) && (inbuf->use - reader->cur <= CHUNK_SIZE)) { val = xmlBufferShrink(inbuf, reader->cur); 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->mode != XML_TEXTREADER_DONE) { s = inbuf->use - reader->cur; val = xmlParseChunk(reader->ctxt, (const char *) &inbuf->content[reader->cur], s, 1); reader->cur = inbuf->use; reader->mode = XML_TEXTREADER_DONE; if ((val != 0) || (reader->ctxt->wellFormed == 0)) return(-1); } } reader->state = oldstate; return(0); } #ifdef LIBXML_REGEXP_ENABLED /** * xmlTextReaderValidatePush: * @reader: the xmlTextReaderPtr used * * Push the current node for validation */ static void xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) { 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 { /* TODO use the BuildQName interface */ xmlChar *qname; qname = xmlStrdup(node->ns->prefix); qname = xmlStrcat(qname, BAD_CAST ":"); qname = xmlStrcat(qname, node->name); reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt, reader->ctxt->myDoc, node, qname); if (qname != NULL) xmlFree(qname); } } #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 = xmlRelaxNGValidatePushElement(reader->rngValidCtxt, reader->ctxt->myDoc, node); if (ret == 0) { /* * this element requires a full tree */ node = xmlTextReaderExpand(reader); if (node == NULL) { printf("Expand failed !\n"); ret = -1; } else { ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt, reader->ctxt->myDoc, node); reader->rngFullNode = node; } } if (ret != 1) reader->rngValidErrors++; } #endif } /** * xmlTextReaderValidateCData: * @reader: the xmlTextReaderPtr used * @data: pointer to the CData * @len: lenght 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 void 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 { /* TODO use the BuildQName interface */ xmlChar *qname; qname = xmlStrdup(node->ns->prefix); qname = xmlStrcat(qname, BAD_CAST ":"); qname = xmlStrcat(qname, node->name); reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt, reader->ctxt->myDoc, node, qname); if (qname != NULL) xmlFree(qname); } } #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; } ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt, reader->ctxt->myDoc, node); if (ret != 1) reader->rngValidErrors++; } #endif } /** * 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 void xmlTextReaderValidateEntity(xmlTextReaderPtr reader) { xmlNodePtr oldnode = reader->node; xmlNodePtr node = reader->node; xmlParserCtxtPtr ctxt = reader->ctxt; do { if (node->type == XML_ENTITY_REF_NODE) { /* * Case where the underlying tree is not availble, lookup the entity * and walk it. */ if ((node->children == NULL) && (ctxt->sax != NULL) && (ctxt->sax->getEntity != NULL)) { node->children = (xmlNodePtr) ctxt->sax->getEntity(ctxt, node->name); } if ((node->children != NULL) && (node->children->type == XML_ENTITY_DECL) && (node->children->children != NULL)) { xmlTextReaderEntPush(reader, node); node = node->children->children; continue; } else { /* * The error has probably be raised already. */ if (node == oldnode) break; node = node->next; } #ifdef LIBXML_REGEXP_ENABLED } else if (node->type == XML_ELEMENT_NODE) { reader->node = node; xmlTextReaderValidatePush(reader); } 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) { xmlTextReaderValidatePop(reader); } 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; xmlTextReaderValidatePop(reader); } 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; } #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 (reader->ctxt->instate == XML_PARSER_EOF) 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) return(-1); } while(reader->mode != XML_TEXTREADER_MODE_EOF); return(1); } /** * xmlTextReaderCollectSiblings: * @node: the first child * * Traverse depth-first through all sibling nodes and their children * nodes and concatenate their content. This is an auxiliary function * to xmlTextReaderReadString. * * Returns a string containing the content, or NULL in case of error. */ static xmlChar * xmlTextReaderCollectSiblings(xmlNodePtr node) { xmlBufferPtr buffer; xmlChar *ret; buffer = xmlBufferCreate(); if (buffer == NULL) return NULL; for ( ; node != NULL; node = node->next) { switch (node->type) { case XML_TEXT_NODE: case XML_CDATA_SECTION_NODE: xmlBufferCat(buffer, node->content); break; case XML_ELEMENT_NODE: { xmlChar *tmp; tmp = xmlTextReaderCollectSiblings(node->children); xmlBufferCat(buffer, tmp); xmlFree(tmp); break; } default: break; } } ret = buffer->content; buffer->content = NULL; xmlBufferFree(buffer); return(ret); } /** * 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); reader->curnode = NULL; if (reader->doc != NULL) return(xmlTextReaderReadTree(reader)); if (reader->ctxt == NULL) return(-1); if (reader->ctxt->wellFormed != 1) return(-1); #ifdef DEBUG_READER fprintf(stderr, "\nREAD "); DUMP_READER #endif if (reader->mode == XML_TEXTREADER_MODE_INITIAL) { reader->mode = XML_TEXTREADER_MODE_INTERACTIVE; /* * Initial state */ do { val = xmlTextReaderPushData(reader); if (val < 0) return(-1); } while ((reader->ctxt->node == NULL) && ((reader->mode != XML_TEXTREADER_MODE_EOF) && (reader->mode != XML_TEXTREADER_DONE))); if (reader->ctxt->node == NULL) { if (reader->ctxt->myDoc != NULL) { reader->node = reader->ctxt->myDoc->children; } if (reader->node == NULL) 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_DONE) return(0); else return(-1); } /* * If we are not backtracking on ancestors or examined nodes, * that the parser didn't finished or that we arent 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)) { val = xmlTextReaderPushData(reader); if (val < 0) 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)) xmlTextReaderValidatePop(reader); #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) && (reader->entNr == 0)) { xmlNodePtr tmp = reader->node->prev; if ((tmp->extra & NODE_IS_PRESERVED) == 0) { 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) && (reader->node->type == XML_ELEMENT_NODE)) xmlTextReaderValidatePop(reader); #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) || #ifdef LIBXML_DOCB_ENABLED (reader->node->type == XML_DOCB_DOCUMENT_NODE) || #endif (reader->node->type == XML_HTML_DOCUMENT_NODE)) { if (reader->mode != XML_TEXTREADER_DONE) { val = xmlParseChunk(reader->ctxt, "", 0, 1); reader->mode = XML_TEXTREADER_DONE; if (val != 0) return(-1); } reader->node = NULL; reader->depth = -1; /* * Cleanup of the old node */ if ((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) && (reader->entNr == 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: DUMP_READER /* * 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->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); xmlXIncludeSetFlags(reader->xincctxt, reader->parserFlags & (~XML_PARSE_NOXINCNODE)); } /* * expand that node and process it */ if (xmlTextReaderExpand(reader) == NULL) return -1; xmlXIncludeProcessNode(reader->xincctxt, reader->node); } 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)) { /* * Case where the underlying tree is not availble, lookup the entity * and walk it. */ if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) && (reader->ctxt->sax->getEntity != NULL)) { reader->node->children = (xmlNodePtr) reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name); } if ((reader->node->children != NULL) && (reader->node->children->type == XML_ENTITY_DECL) && (reader->node->children->children != NULL)) { xmlTextReaderEntPush(reader, reader->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)) { xmlTextReaderValidateEntity(reader); #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) && (reader->node != NULL)) { xmlNodePtr node = reader->node; if ((node->type == XML_ELEMENT_NODE) && ((reader->state != XML_TEXTREADER_END) && (reader->state != XML_TEXTREADER_BACKTRACK))) { xmlTextReaderValidatePush(reader); } 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->mode = 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 /** * 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 ATTRIBUTE_UNUSED) { xmlChar *resbuf; xmlNodePtr node, cur_node; xmlBufferPtr buff, buff2; xmlDocPtr doc; if (xmlTextReaderExpand(reader) == NULL) { return NULL; } doc = reader->doc; buff = xmlBufferCreate(); for (cur_node = reader->node->children; cur_node != NULL; cur_node = cur_node->next) { node = xmlDocCopyNode(cur_node, doc, 1); buff2 = xmlBufferCreate(); if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) { xmlFreeNode(node); xmlBufferFree(buff2); xmlBufferFree(buff); return NULL; } xmlBufferCat(buff, buff2->content); xmlFreeNode(node); xmlBufferFree(buff2); } resbuf = buff->content; buff->content = NULL; xmlBufferFree(buff); return resbuf; } #endif #ifdef LIBXML_WRITER_ENABLED /** * xmlTextReaderReadOuterXml: * @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 * xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) { xmlChar *resbuf; xmlNodePtr node; xmlBufferPtr buff; xmlDocPtr doc; node = reader->node; doc = reader->doc; if (xmlTextReaderExpand(reader) == NULL) { return NULL; } node = xmlDocCopyNode(node, doc, 1); buff = xmlBufferCreate(); if (xmlNodeDump(buff, doc, node, 0, 0) == -1) { xmlFreeNode(node); xmlBufferFree(buff); return NULL; } resbuf = buff->content; buff->content = NULL; xmlFreeNode(node); xmlBufferFree(buff); return resbuf; } #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; if ((reader == NULL) || (reader->node == NULL)) return(NULL); node = (reader->curnode != NULL) ? reader->curnode : reader->node; switch (node->type) { case XML_TEXT_NODE: if (node->content != NULL) return(xmlStrdup(node->content)); break; case XML_ELEMENT_NODE: if (xmlTextReaderDoExpand(reader) != -1) { return xmlTextReaderCollectSiblings(node->children); } case XML_ATTRIBUTE_NODE: TODO break; default: break; } return(NULL); } #if 0 /** * xmlTextReaderReadBase64: * @reader: the xmlTextReaderPtr used * @array: a byte array to store the content. * @offset: the zero-based index into array where the method should * begin to write. * @len: the number of bytes to write. * * Reads and decodes the Base64 encoded contents of an element and * stores the result in a byte buffer. * * Returns the number of bytes written to array, or zero if the current * instance is not positioned on an element or -1 in case of error. */ int xmlTextReaderReadBase64(xmlTextReaderPtr reader, unsigned char *array ATTRIBUTE_UNUSED, int offset ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED) { if ((reader == NULL) || (reader->ctxt == NULL)) return(-1); if (reader->ctxt->wellFormed != 1) return(-1); if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE)) return(0); TODO return(0); } /** * xmlTextReaderReadBinHex: * @reader: the xmlTextReaderPtr used * @array: a byte array to store the content. * @offset: the zero-based index into array where the method should * begin to write. * @len: the number of bytes to write. * * Reads and decodes the BinHex encoded contents of an element and * stores the result in a byte buffer. * * Returns the number of bytes written to array, or zero if the current * instance is not positioned on an element or -1 in case of error. */ int xmlTextReaderReadBinHex(xmlTextReaderPtr reader, unsigned char *array ATTRIBUTE_UNUSED, int offset ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED) { if ((reader == NULL) || (reader->ctxt == NULL)) return(-1); if (reader->ctxt->wellFormed != 1) return(-1); if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE)) return(0); TODO return(0); } #endif /************************************************************************ * * * 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) { if (reader->node->children != 0) { reader->node = reader->node->children; reader->depth++; reader->state = XML_TEXTREADER_START; return(1); } if ((reader->node->type == XML_ELEMENT_NODE) || (reader->node->type == XML_ATTRIBUTE_NODE)) { reader->state = XML_TEXTREADER_BACKTRACK; return(1); } } 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; return(1); } 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) { xmlGenericError(xmlGenericErrorContext, "xmlNewTextReader : malloc failed\n"); return(NULL); } memset(ret, 0, sizeof(xmlTextReader)); ret->doc = NULL; ret->entTab = NULL; ret->entMax = 0; ret->entNr = 0; ret->input = input; ret->buffer = xmlBufferCreateSize(100); if (ret->buffer == NULL) { xmlFree(ret); xmlGenericError(xmlGenericErrorContext, "xmlNewTextReader : malloc failed\n"); return(NULL); } ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler)); if (ret->sax == NULL) { xmlBufferFree(ret->buffer); xmlFree(ret); xmlGenericError(xmlGenericErrorContext, "xmlNewTextReader : malloc failed\n"); 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 (ret->input->buffer->use < 4) { xmlParserInputBufferRead(input, 4); } if (ret->input->buffer->use >= 4) { ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, (const char *) ret->input->buffer->content, 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) { xmlGenericError(xmlGenericErrorContext, "xmlNewTextReader : malloc failed\n"); xmlBufferFree(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 dictionnary to allocate all elements and attributes names */ ret->ctxt->docdict = 1; 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; char *directory = NULL; 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; if (ret->ctxt->directory == NULL) directory = xmlParserGetDirectory(URI); if ((ret->ctxt->directory == NULL) && (directory != NULL)) ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory); if (directory != NULL) xmlFree(directory); 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) { 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->ctxt != NULL) { if (reader->dict == reader->ctxt->dict) reader->dict = NULL; if (reader->ctxt->myDoc != NULL) { if (reader->preserve == 0) xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc); reader->ctxt->myDoc = NULL; } if ((reader->ctxt->vctxt.vstateTab != NULL) && (reader->ctxt->vctxt.vstateMax > 0)){ xmlFree(reader->ctxt->vctxt.vstateTab); reader->ctxt->vctxt.vstateTab = NULL; reader->ctxt->vctxt.vstateMax = 0; } if (reader->allocs & XML_TEXTREADER_CTXT) xmlFreeParserCtxt(reader->ctxt); } if (reader->sax != NULL) xmlFree(reader->sax); if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) xmlFreeParserInputBuffer(reader->input); if (reader->faketext != NULL) { xmlFreeNode(reader->faketext); } if (reader->buffer != NULL) xmlBufferFree(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->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->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(xmlStrdup(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) return(xmlStrdup((xmlChar *)"")); 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; xmlChar *localname; xmlNsPtr ns; xmlChar *ret = NULL; 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 = xmlSplitQName2(name, &prefix); if (localname == NULL) { /* * Namespace default decl */ if (xmlStrEqual(name, BAD_CAST "xmlns")) { ns = reader->node->nsDef; while (ns != NULL) { if (ns->prefix == NULL) { return(xmlStrdup(ns->href)); } ns = ns->next; } return NULL; } return(xmlGetNoNsProp(reader->node, name)); } /* * 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 = xmlStrdup(ns->href); break; } ns = ns->next; } } else { ns = xmlSearchNs(reader->node->doc, reader->node, prefix); if (ns != NULL) ret = xmlGetNsProp(reader->node, localname, ns->href); } xmlFree(localname); 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 *prefix = NULL; xmlNsPtr ns; 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 xmlStrdup(ns->href); } ns = ns->next; } return NULL; } return(xmlGetNsProp(reader->node, localName, namespaceURI)); } /** * 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 procgressed 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. */ TODO 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; if (reader == NULL) return(NULL); if (reader->node == NULL) return(NULL); ns = xmlSearchNs(reader->node->doc, reader->node, prefix); if (ns == NULL) return(NULL); return(xmlStrdup(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; 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 = xmlSplitQName2(name, &prefix); if (localname == 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 (localname != NULL) xmlFree(localname); if (prefix != NULL) xmlFree(prefix); return(0); found: if (localname != NULL) xmlFree(localname); 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 positionned on an * ttribute 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); } else { if ((reader->faketext->content != NULL) && (reader->faketext->content != (xmlChar *) &(reader->faketext->properties))) xmlFree(reader->faketext->content); reader->faketext->content = xmlStrdup(ns->href); } 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) { 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->encoding == NULL) return(NULL); else return(CONSTSTR(doc->encoding)); } /************************************************************************ * * * Acces 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://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html * * Returns the xmlNodeType 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: #ifdef LIBXML_DOCB_ENABLED case XML_DOCB_DOCUMENT_NODE: #endif 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 */ 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(xmlStrdup(BAD_CAST "xmlns")); else return(xmlStrdup(ns->prefix)); } if ((node->type != XML_ELEMENT_NODE) && (node->type != XML_ATTRIBUTE_NODE)) return(xmlTextReaderName(reader)); return(xmlStrdup(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(CONSTSTR(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 */ 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(xmlStrdup(node->name)); ret = xmlStrdup(node->ns->prefix); ret = xmlStrcat(ret, BAD_CAST ":"); ret = xmlStrcat(ret, node->name); return(ret); case XML_TEXT_NODE: return(xmlStrdup(BAD_CAST "#text")); case XML_CDATA_SECTION_NODE: return(xmlStrdup(BAD_CAST "#cdata-section")); case XML_ENTITY_NODE: case XML_ENTITY_REF_NODE: return(xmlStrdup(node->name)); case XML_PI_NODE: return(xmlStrdup(node->name)); case XML_COMMENT_NODE: return(xmlStrdup(BAD_CAST "#comment")); case XML_DOCUMENT_NODE: case XML_HTML_DOCUMENT_NODE: #ifdef LIBXML_DOCB_ENABLED case XML_DOCB_DOCUMENT_NODE: #endif return(xmlStrdup(BAD_CAST "#document")); case XML_DOCUMENT_FRAG_NODE: return(xmlStrdup(BAD_CAST "#document-fragment")); case XML_NOTATION_NODE: return(xmlStrdup(node->name)); case XML_DOCUMENT_TYPE_NODE: case XML_DTD_NODE: return(xmlStrdup(node->name)); case XML_NAMESPACE_DECL: { xmlNsPtr ns = (xmlNsPtr) node; ret = xmlStrdup(BAD_CAST "xmlns"); if (ns->prefix == NULL) return(ret); ret = xmlStrcat(ret, BAD_CAST ":"); ret = xmlStrcat(ret, ns->prefix); 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(CONSTQSTR(node->ns->prefix, node->name)); case XML_TEXT_NODE: return(CONSTSTR(BAD_CAST "#text")); case XML_CDATA_SECTION_NODE: return(CONSTSTR(BAD_CAST "#cdata-section")); case XML_ENTITY_NODE: case XML_ENTITY_REF_NODE: return(CONSTSTR(node->name)); case XML_PI_NODE: return(CONSTSTR(node->name)); case XML_COMMENT_NODE: return(CONSTSTR(BAD_CAST "#comment")); case XML_DOCUMENT_NODE: case XML_HTML_DOCUMENT_NODE: #ifdef LIBXML_DOCB_ENABLED case XML_DOCB_DOCUMENT_NODE: #endif return(CONSTSTR(BAD_CAST "#document")); case XML_DOCUMENT_FRAG_NODE: return(CONSTSTR(BAD_CAST "#document-fragment")); case XML_NOTATION_NODE: return(CONSTSTR(node->name)); case XML_DOCUMENT_TYPE_NODE: case XML_DTD_NODE: return(CONSTSTR(node->name)); case XML_NAMESPACE_DECL: { xmlNsPtr ns = (xmlNsPtr) node; if (ns->prefix == NULL) return(CONSTSTR(BAD_CAST "xmlns")); return(CONSTQSTR(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 */ 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(xmlStrdup(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(xmlStrdup(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(CONSTSTR(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(CONSTSTR(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 */ 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(xmlStrdup(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(xmlStrdup(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(CONSTSTR(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(CONSTSTR(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 */ xmlChar * xmlTextReaderBaseUri(xmlTextReaderPtr reader) { if ((reader == NULL) || (reader->node == NULL)) return(NULL); return(xmlNodeGetBase(NULL, reader->node)); } /** * 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; if ((reader == NULL) || (reader->node == NULL)) return(NULL); tmp = xmlNodeGetBase(NULL, reader->node); if (tmp == NULL) return(NULL); ret = CONSTSTR(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(xmlStrdup(((xmlNsPtr) node)->href)); case XML_ATTRIBUTE_NODE:{ xmlAttrPtr attr = (xmlAttrPtr) node; if (attr->parent != NULL) return (xmlNodeListGetString (attr->parent->doc, attr->children, 1)); else return (xmlNodeListGetString(NULL, attr->children, 1)); break; } case XML_TEXT_NODE: case XML_CDATA_SECTION_NODE: case XML_PI_NODE: case XML_COMMENT_NODE: if (node->content != NULL) return (xmlStrdup(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; 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 = xmlBufferCreateSize(100); if (reader->buffer == NULL) { xmlGenericError(xmlGenericErrorContext, "xmlTextReaderSetup : malloc failed\n"); return (NULL); } reader->buffer->use = 0; xmlNodeBufGetContent(reader->buffer, node); return(reader->buffer->content); } 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((int) '"'); } /** * xmlTextReaderXmlLang: * @reader: the xmlTextReaderPtr used * * The xml:lang scope within which the node resides. * * Returns the xml:lang value or NULL if none exists. */ 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 = CONSTSTR(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(CONSTSTR(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 bahaviour 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->loadsubset = XML_DETECT_IDS; } } else { ctxt->loadsubset = 0; } return(0); case XML_PARSER_DEFAULTATTRS: if (value != 0) { ctxt->loadsubset |= XML_COMPLETE_ATTRS; } else { if (ctxt->loadsubset & XML_COMPLETE_ATTRS) ctxt->loadsubset -= XML_COMPLETE_ATTRS; } return(0); case XML_PARSER_VALIDATE: if (value != 0) { ctxt->validate = 1; reader->validate = XML_TEXTREADER_VALIDATE_DTD; } else { ctxt->validate = 0; } return(0); case XML_PARSER_SUBST_ENTITIES: if (value != 0) { ctxt->replaceEntities = 1; } else { 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 correponding 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); if (reader->curnode != NULL) cur = reader->curnode; else 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 positive 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) { xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n"); 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) { xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n"); 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 correponding 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 == NULL) || (reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL)) return(NULL); reader->preserve = 1; return(reader->ctxt->myDoc); } #ifdef LIBXML_SCHEMAS_ENABLED static char * xmlTextReaderBuildMessage(const char *msg, va_list ap); static void XMLCDECL xmlTextReaderValidityError(void *ctxt, const char *msg, ...); static void XMLCDECL xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...); static void XMLCDECL xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...) { xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx; char * str; va_list ap; va_start(ap,msg); str = xmlTextReaderBuildMessage(msg,ap); if (!reader->errorFunc) { xmlTextReaderValidityError(ctx, "%s", str); } else { reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_ERROR, NULL /* locator */); } if (str != NULL) xmlFree(str); va_end(ap); } static void XMLCDECL xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...) { xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx; char * str; va_list ap; va_start(ap,msg); str = xmlTextReaderBuildMessage(msg,ap); if (!reader->errorFunc) { xmlTextReaderValidityWarning(ctx, "%s", str); } else { reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_WARNING, NULL /* locator */); } if (str != NULL) xmlFree(str); va_end(ap); } static void xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error); static void xmlTextReaderValidityStructuredRelay(void * userData, xmlErrorPtr error) { xmlTextReaderPtr reader = (xmlTextReaderPtr) userData; if (reader->sErrorFunc) { reader->sErrorFunc(reader->errorFuncArg, error); } else { xmlTextReaderStructuredError(reader, error); } } /** * 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 desactivated. @ 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 (des)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) { xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); reader->rngValidCtxt = NULL; } 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) { xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); reader->rngValidCtxt = NULL; } reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema); if (reader->rngValidCtxt == NULL) return(-1); if (reader->errorFunc != NULL) { xmlRelaxNGSetValidErrors(reader->rngValidCtxt, xmlTextReaderValidityErrorRelay, xmlTextReaderValidityWarningRelay, reader); } if (reader->sErrorFunc != NULL) { xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, xmlTextReaderValidityStructuredRelay, reader); } reader->rngValidErrors = 0; reader->rngFullNode = NULL; reader->validate = XML_TEXTREADER_VALIDATE_RNG; return(0); } /** * 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 desactivated. @ 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 (des)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); } if (reader->errorFunc != NULL) { xmlSchemaSetValidErrors(reader->xsdValidCtxt, xmlTextReaderValidityErrorRelay, xmlTextReaderValidityWarningRelay, reader); } if (reader->sErrorFunc != NULL) { xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, xmlTextReaderValidityStructuredRelay, reader); } reader->xsdValidErrors = 0; reader->validate = XML_TEXTREADER_VALIDATE_XSD; return(0); } /** * xmlTextReaderRelaxNGValidate: * @reader: the xmlTextReaderPtr used * @rng: the path to a RelaxNG schema or NULL * * Use RelaxNG to validate the document as it is processed. * Activation is only possible before the first Read(). * if @rng is NULL, then RelaxNG validation is desactivated. * * Returns 0 in case the RelaxNG validation could be (des)activated and * -1 in case of error. */ int xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) { xmlRelaxNGParserCtxtPtr ctxt; if (reader == NULL) return(-1); if (rng == NULL) { if (reader->rngValidCtxt != NULL) { xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); reader->rngValidCtxt = NULL; } if (reader->rngSchemas != NULL) { xmlRelaxNGFree(reader->rngSchemas); reader->rngSchemas = NULL; } 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) { xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); reader->rngValidCtxt = NULL; } ctxt = xmlRelaxNGNewParserCtxt(rng); if (reader->errorFunc != NULL) { xmlRelaxNGSetParserErrors(ctxt, xmlTextReaderValidityErrorRelay, xmlTextReaderValidityWarningRelay, reader); } if (reader->sErrorFunc != NULL) { xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, xmlTextReaderValidityStructuredRelay, reader); } reader->rngSchemas = xmlRelaxNGParse(ctxt); xmlRelaxNGFreeParserCtxt(ctxt); if (reader->rngSchemas == NULL) return(-1); reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas); if (reader->rngValidCtxt == NULL) { xmlRelaxNGFree(reader->rngSchemas); reader->rngSchemas = NULL; return(-1); } if (reader->errorFunc != NULL) { xmlRelaxNGSetValidErrors(reader->rngValidCtxt, xmlTextReaderValidityErrorRelay, xmlTextReaderValidityWarningRelay, reader); } if (reader->sErrorFunc != NULL) { xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, xmlTextReaderValidityStructuredRelay, 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) { xmlSchemaSetParserErrors(pctxt, xmlTextReaderValidityErrorRelay, xmlTextReaderValidityWarningRelay, 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); } } /* * 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) { xmlSchemaSetValidErrors(reader->xsdValidCtxt, xmlTextReaderValidityErrorRelay, xmlTextReaderValidityWarningRelay, reader); } if (reader->sErrorFunc != NULL) { xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, xmlTextReaderValidityStructuredRelay, 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)); } #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(CONSTSTR(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 * * * ************************************************************************/ /* helper to build a xmlMalloc'ed string from a format and va_list */ static char * xmlTextReaderBuildMessage(const char *msg, va_list ap) { int size; int chars; char *larger; char *str; str = (char *) xmlMallocAtomic(150); if (str == NULL) { xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n"); return NULL; } size = 150; while (1) { chars = vsnprintf(str, size, msg, ap); if ((chars > -1) && (chars < size)) break; if (chars > -1) size += chars + 1; else size += 100; if ((larger = (char *) xmlRealloc(str, size)) == NULL) { xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n"); xmlFree(str); return NULL; } str = larger; } return str; } /** * 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. */ 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; } static void xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) { xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt; xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private; if (str != NULL) { if (reader->errorFunc) reader->errorFunc(reader->errorFuncArg, str, severity, (xmlTextReaderLocatorPtr)ctx); xmlFree(str); } } static void xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error) { xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt; xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private; if (error && reader->sErrorFunc) { reader->sErrorFunc(reader->errorFuncArg, (xmlErrorPtr) error); } } static void XMLCDECL xmlTextReaderError(void *ctxt, const char *msg, ...) { va_list ap; va_start(ap,msg); xmlTextReaderGenericError(ctxt, XML_PARSER_SEVERITY_ERROR, xmlTextReaderBuildMessage(msg,ap)); va_end(ap); } static void XMLCDECL xmlTextReaderWarning(void *ctxt, const char *msg, ...) { va_list ap; va_start(ap,msg); xmlTextReaderGenericError(ctxt, XML_PARSER_SEVERITY_WARNING, xmlTextReaderBuildMessage(msg,ap)); va_end(ap); } static void XMLCDECL xmlTextReaderValidityError(void *ctxt, const char *msg, ...) { va_list ap; int len = xmlStrlen((const xmlChar *) msg); if ((len > 1) && (msg[len - 2] != ':')) { /* * some callbacks only report locator information: * skip them (mimicking behaviour in error.c) */ va_start(ap,msg); xmlTextReaderGenericError(ctxt, XML_PARSER_SEVERITY_VALIDITY_ERROR, xmlTextReaderBuildMessage(msg,ap)); va_end(ap); } } static void XMLCDECL xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) { va_list ap; int len = xmlStrlen((const xmlChar *) msg); if ((len != 0) && (msg[len - 1] != ':')) { /* * some callbacks only report locator information: * skip them (mimicking behaviour in error.c) */ va_start(ap,msg); xmlTextReaderGenericError(ctxt, XML_PARSER_SEVERITY_VALIDITY_WARNING, xmlTextReaderBuildMessage(msg,ap)); va_end(ap); } } /** * 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 * * 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->ctxt->sax->error = xmlTextReaderError; reader->ctxt->sax->serror = NULL; reader->ctxt->vctxt.error = xmlTextReaderValidityError; reader->ctxt->sax->warning = xmlTextReaderWarning; reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning; reader->errorFunc = f; reader->sErrorFunc = NULL; reader->errorFuncArg = arg; #ifdef LIBXML_SCHEMAS_ENABLED if (reader->rngValidCtxt) { xmlRelaxNGSetValidErrors(reader->rngValidCtxt, xmlTextReaderValidityErrorRelay, xmlTextReaderValidityWarningRelay, reader); xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader); } if (reader->xsdValidCtxt) { xmlSchemaSetValidErrors(reader->xsdValidCtxt, xmlTextReaderValidityErrorRelay, xmlTextReaderValidityWarningRelay, reader); xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader); } #endif } else { /* restore defaults */ reader->ctxt->sax->error = xmlParserError; reader->ctxt->vctxt.error = xmlParserValidityError; reader->ctxt->sax->warning = xmlParserWarning; reader->ctxt->vctxt.warning = xmlParserValidityWarning; reader->errorFunc = NULL; reader->sErrorFunc = NULL; reader->errorFuncArg = NULL; #ifdef LIBXML_SCHEMAS_ENABLED if (reader->rngValidCtxt) { xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader); xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader); } if (reader->xsdValidCtxt) { xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader); xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader); } #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->ctxt->sax->error = NULL; reader->ctxt->sax->serror = xmlTextReaderStructuredError; reader->ctxt->vctxt.error = xmlTextReaderValidityError; reader->ctxt->sax->warning = xmlTextReaderWarning; reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning; reader->sErrorFunc = f; reader->errorFunc = NULL; reader->errorFuncArg = arg; #ifdef LIBXML_SCHEMAS_ENABLED if (reader->rngValidCtxt) { xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader); xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, xmlTextReaderValidityStructuredRelay, reader); } if (reader->xsdValidCtxt) { xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader); xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, xmlTextReaderValidityStructuredRelay, reader); } #endif } else { /* restore defaults */ reader->ctxt->sax->error = xmlParserError; reader->ctxt->sax->serror = NULL; reader->ctxt->vctxt.error = xmlParserValidityError; reader->ctxt->sax->warning = xmlParserWarning; reader->ctxt->vctxt.warning = xmlParserValidityWarning; reader->errorFunc = NULL; reader->sErrorFunc = NULL; reader->errorFuncArg = NULL; #ifdef LIBXML_SCHEMAS_ENABLED if (reader->rngValidCtxt) { xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader); xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader); } if (reader->xsdValidCtxt) { xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader); xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader); } #endif } } /** * 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); } /** * 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; } /************************************************************************ * * * New set (2.6.0) of simpler and more flexible APIs * * * ************************************************************************/ /** * xmlTextReaderSetup: * @reader: an XML reader * @URL: the base URL to use for the document * @encoding: the document encoding, or NULL * @options: a combination of xmlParserOption * @reuse: keep the context for reuse * * Setup an XML reader with new options * * Returns 0 in case of success and -1 in case of error. */ static int xmlTextReaderSetup(xmlTextReaderPtr reader, xmlParserInputBufferPtr input, const char *URL, const char *encoding, int options) { if (reader == NULL) 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 = xmlBufferCreateSize(100); if (reader->buffer == NULL) { xmlGenericError(xmlGenericErrorContext, "xmlTextReaderSetup : malloc failed\n"); return (-1); } if (reader->sax == NULL) reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler)); if (reader->sax == NULL) { xmlGenericError(xmlGenericErrorContext, "xmlTextReaderSetup : malloc failed\n"); 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 (reader->input->buffer->use < 4) { xmlParserInputBufferRead(input, 4); } if (reader->ctxt == NULL) { if (reader->input->buffer->use >= 4) { reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL, (const char *) reader->input->buffer->content, 4, URL); reader->base = 0; reader->cur = 4; } else { reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL); reader->base = 0; reader->cur = 0; } } else { xmlParserInputPtr inputStream; xmlParserInputBufferPtr buf; xmlCharEncoding enc = XML_CHAR_ENCODING_NONE; xmlCtxtReset(reader->ctxt); buf = xmlAllocParserInputBuffer(enc); 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; inputStream->base = inputStream->buf->buffer->content; inputStream->cur = inputStream->buf->buffer->content; inputStream->end = &inputStream->buf->buffer->content[inputStream->buf->buffer->use]; inputPush(reader->ctxt, inputStream); reader->cur = 0; } if (reader->ctxt == NULL) { xmlGenericError(xmlGenericErrorContext, "xmlTextReaderSetup : malloc failed\n"); return (-1); } } 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 dictionnary to allocate all elements and attributes names */ reader->ctxt->docdict = 1; 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); 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) { xmlCharEncodingHandlerPtr hdlr; hdlr = xmlFindCharEncodingHandler(encoding); if (hdlr != NULL) xmlSwitchToEncoding(reader->ctxt, hdlr); } if ((URL != NULL) && (reader->ctxt->input != NULL) && (reader->ctxt->input->filename == NULL)) reader->ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) URL); reader->doc = NULL; return (0); } /** * xmlTextReaderByteConsumed: * @reader: an XML reader * * 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) { if ((reader == NULL) || (reader->ctxt == NULL)) return(-1); return(xmlByteConsumed(reader->ctxt)); } /** * 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) { xmlGenericError(xmlGenericErrorContext, "xmlNewTextReader : malloc failed\n"); 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); xmlTextReaderSetup(reader, NULL, NULL, encoding, options); 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 = xmlParserInputBufferCreateStatic(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; xmlTextReaderSetup(reader, NULL, URL, encoding, options); 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; xmlTextReaderSetup(reader, NULL, URL, encoding, options); 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) return (NULL); reader = xmlNewTextReader(input, URL); if (reader == NULL) { xmlFreeParserInputBuffer(input); return (NULL); } reader->allocs |= XML_TEXTREADER_INPUT; xmlTextReaderSetup(reader, NULL, URL, encoding, options); 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 = xmlParserInputBufferCreateStatic(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) return (-1); return (xmlTextReaderSetup(reader, input, URL, encoding, options)); } /************************************************************************ * * * Utilities * * * ************************************************************************/ #ifdef NOT_USED_YET /** * xmlBase64Decode: * @in: the input buffer * @inlen: the size of the input (in), the size read from it (out) * @to: the output buffer * @tolen: the size of the output (in), the size written to (out) * * Base64 decoder, reads from @in and save in @to * TODO: tell jody when this is actually exported * * Returns 0 if all the input was consumer, 1 if the Base64 end was reached, * 2 if there wasn't enough space on the output or -1 in case of error. */ static int xmlBase64Decode(const unsigned char *in, unsigned long *inlen, unsigned char *to, unsigned long *tolen) { unsigned long incur; /* current index in in[] */ unsigned long inblk; /* last block index in in[] */ unsigned long outcur; /* current index in out[] */ unsigned long inmax; /* size of in[] */ unsigned long outmax; /* size of out[] */ unsigned char cur; /* the current value read from in[] */ unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */ int nbintmp; /* number of byte in intmp[] */ int is_ignore; /* cur should be ignored */ int is_end = 0; /* the end of the base64 was found */ int retval = 1; int i; if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL)) return(-1); incur = 0; inblk = 0; outcur = 0; inmax = *inlen; outmax = *tolen; nbintmp = 0; while (1) { if (incur >= inmax) break; cur = in[incur++]; is_ignore = 0; if ((cur >= 'A') && (cur <= 'Z')) cur = cur - 'A'; else if ((cur >= 'a') && (cur <= 'z')) cur = cur - 'a' + 26; else if ((cur >= '0') && (cur <= '9')) cur = cur - '0' + 52; else if (cur == '+') cur = 62; else if (cur == '/') cur = 63; else if (cur == '.') cur = 0; else if (cur == '=') /*no op , end of the base64 stream */ is_end = 1; else { is_ignore = 1; if (nbintmp == 0) inblk = incur; } if (!is_ignore) { int nbouttmp = 3; int is_break = 0; if (is_end) { if (nbintmp == 0) break; if ((nbintmp == 1) || (nbintmp == 2)) nbouttmp = 1; else nbouttmp = 2; nbintmp = 3; is_break = 1; } intmp[nbintmp++] = cur; /* * if intmp is full, push the 4byte sequence as a 3 byte * sequence out */ if (nbintmp == 4) { nbintmp = 0; outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4); outtmp[1] = ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2); outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F); if (outcur + 3 >= outmax) { retval = 2; break; } for (i = 0; i < nbouttmp; i++) to[outcur++] = outtmp[i]; inblk = incur; } if (is_break) { retval = 0; break; } } } *tolen = outcur; *inlen = inblk; return (retval); } /* * Test routine for the xmlBase64Decode function */ #if 0 int main(int argc, char **argv) { char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== "; char output[100]; char output2[100]; char output3[100]; unsigned long inlen = strlen(input); unsigned long outlen = 100; int ret; unsigned long cons, tmp, tmp2, prod; /* * Direct */ ret = xmlBase64Decode(input, &inlen, output, &outlen); output[outlen] = 0; printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output); /* * output chunking */ cons = 0; prod = 0; while (cons < inlen) { tmp = 5; tmp2 = inlen - cons; printf("%ld %ld\n", cons, prod); ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp); cons += tmp2; prod += tmp; printf("%ld %ld\n", cons, prod); } output2[outlen] = 0; printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2); /* * input chunking */ cons = 0; prod = 0; while (cons < inlen) { tmp = 100 - prod; tmp2 = inlen - cons; if (tmp2 > 5) tmp2 = 5; printf("%ld %ld\n", cons, prod); ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp); cons += tmp2; prod += tmp; printf("%ld %ld\n", cons, prod); } output3[outlen] = 0; printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3); return(0); } #endif #endif /* NOT_USED_YET */ #define bottom_xmlreader #include "elfgcchack.h" #endif /* LIBXML_READER_ENABLED */
xmlreader.c
Page URL
File URL
Prev
105/114
Next
Download
( 160 KB )
Note: The DriveHQ service banners will NOT be displayed if the file owner is a paid member.
Comments
Total ratings:
0
Average rating:
Not Rated
Would you like to comment?
Join DriveHQ
for a free account, or
Logon
if you are already a member.