blob: 560c946ef3b7652dae48e8ce675cf2aca78876c6 [file] [log] [blame]
/*
* xmldwalk.c : the document traversing API.for XML
*
* this is heavily based upon the xmlTextReader streaming node API
* of libxml2 by Daniel Veillard (daniel@veillard.com). In fact I
* just copied and modified xmlreader.c
*
* So for license and disclaimer see the license and disclaimer of
* libxml2.
*
* alfred@mickautsch.de
*/
#define IN_LIBXML
#include "libxml.h"
#ifdef LIBXML_WALKER_ENABLED
#include <string.h>
#include <libxml/xmlmemory.h>
#include <libxml/xmlIO.h>
#include <libxml/xmlreader.h>
#include <libxml/xmldwalk.h>
struct _xmlDocWalker {
xmlDocPtr doc; /* current document */
xmlNodePtr node; /* current node */
xmlNodePtr curnode; /* current attribute node */
int depth; /* depth of the current node */
xmlDocWalkerState state; /* state of the iterator */
};
/**
* xmlNewDocWalker:
* @doc: the xmlDocPtr
*
* Creates a new instance of the xmlDocWalker
*
* Returns 0 in case of error, the new allocated xmlDocWalkerPtr otherwise
*/
xmlDocWalkerPtr
xmlNewDocWalker(xmlDocPtr doc)
{
xmlDocWalkerPtr ret;
if (doc == 0)
return(0);
ret = xmlMalloc(sizeof(xmlDocWalker));
if (ret == 0) {
xmlGenericError(xmlGenericErrorContext,
"xmlNewDocWalker : malloc failed\n");
return(0);
}
memset(ret, 0, sizeof(xmlDocWalker));
ret->doc = doc;
ret->node = 0;
ret->state = XML_DWALK_NONE;
return ret;
}
/**
* xmlFreeDocWalker:
* @iter: the xmlDocWalkerPtr
*
* Deallocate the xmlDocWalker
*/
void
xmlFreeDocWalker(xmlDocWalkerPtr iter)
{
if (iter != 0)
xmlFree(iter);
}
/**
* xmlDocWalkerRewind:
* @iter: the xmlDocWalkerPtr
*
* Initializes the xmlDocWalker
*
* Returns 0 or -1 in case of error
*/
int
xmlDocWalkerRewind(xmlDocWalkerPtr iter)
{
if (iter == 0 || iter->doc == 0)
return(-1);
if (iter->doc->children == 0)
return(0);
iter->state = XML_DWALK_NONE;
iter->depth = 0;
iter->node = 0;
return(1);
}
/**
* xmlDocWalkerStep:
* @iter: the xmlDocWalkerPtr
*
* Steps through the xml tree
*
* Returns 0 or -1 in case of error
*/
int
xmlDocWalkerStep(xmlDocWalkerPtr iter)
{
if (iter == 0)
return(-1);
if (iter->state == XML_DWALK_END)
return(0);
if (iter->node == 0) {
if (iter->doc->children == 0) {
iter->state = XML_DWALK_END;
return(0);
}
iter->node = iter->doc->children;
iter->state = XML_DWALK_START;
return(1);
}
if (iter->state != XML_DWALK_BACKTRACK) {
if (iter->node->children != 0) {
iter->node = iter->node->children;
iter->depth++;
iter->state = XML_DWALK_START;
return(1);
}
if ((iter->node->type == XML_ELEMENT_NODE) ||
(iter->node->type == XML_ATTRIBUTE_NODE)) {
iter->state = XML_DWALK_BACKTRACK;
return(1);
}
}
if (iter->node->next != 0) {
iter->node = iter->node->next;
iter->state = XML_DWALK_START;
return(1);
}
if (iter->node->parent != 0) {
if (iter->node->parent->type == XML_DOCUMENT_NODE) {
iter->state = XML_DWALK_END;
return(0);
}
iter->node = iter->node->parent;
iter->depth--;
iter->state = XML_DWALK_BACKTRACK;
return(1);
}
iter->state = XML_DWALK_END;
return(1);
}
/**
* xmlDocWalkerAttributeCount:
* @iter: the xmlDocWalkerPtr
*
* Provides the number of attributes of the current node
*
* Returns 0 if no attributes, -1 in case of error or the attribute count
*/
int
xmlDocWalkerAttributeCount(xmlDocWalkerPtr iter)
{
int ret;
xmlAttrPtr attr;
xmlNsPtr ns;
xmlNodePtr node;
if (iter == 0)
return(-1);
if (iter->node == 0)
return(0);
if (iter->curnode != 0)
node = iter->curnode;
else
node = iter->node;
if (node->type != XML_ELEMENT_NODE)
return(0);
ret = 0;
attr = node->properties;
while (attr != 0) {
ret++;
attr = attr->next;
}
ns = node->nsDef;
while (ns != 0) {
ret++;
ns = ns->next;
}
return ret;
}
/**
* xmlDocWalkerDepth:
* @iter: the xmlDocWalkerPtr
*
* The depth of the node in the tree.
*
* Returns the depth or -1 in case of error
*/
int
xmlDocWalkerDepth(xmlDocWalkerPtr iter)
{
if (iter == 0)
return(-1);
if (iter->node == 0)
return(0);
if (iter->curnode != 0) {
if ((iter->curnode->type == XML_ATTRIBUTE_NODE) ||
(iter->curnode->type == XML_NAMESPACE_DECL))
return iter->depth + 1;
return iter->depth + 2;
}
return iter->depth;
}
/**
* xmlDocWalkerHasAttributes:
* @iter: the xmlDocWalkerPtr
*
* Whether the node has attributes.
*
* Returns 1 if true, 0 if false, and -1 in case or error
*/
int
xmlDocWalkerHasAttributes(xmlDocWalkerPtr iter)
{
xmlNodePtr node;
if (iter == 0)
return(-1);
if (iter->node == 0)
return(0);
if (iter->curnode != 0)
node = iter->curnode;
else
node = iter->node;
if ((node->type == XML_ELEMENT_NODE) && (node->properties != 0))
return(1);
return(0);
}
/**
* xmlDocWalkerHasValue:
* @iter: the xmlDocWalkerPtr
*
* Whether the node can have a text value.
*
* Returns 1 if true, 0 if false, and -1 in case or error
*/
int
xmlDocWalkerHasValue(xmlDocWalkerPtr iter)
{
xmlNodePtr node;
if (iter == 0)
return(-1);
if (iter->node == 0)
return(0);
if (iter->curnode != 0)
node = iter->curnode;
else
node = iter->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);
}
/**
* xmlDocWalkerIsEmptyElement:
* @iter: the xmlDocWalkerPtr
*
* Check if the current node is empty
*
* Returns 1 if empty, 0 if not and -1 in case of error
*/
int
xmlDocWalkerIsEmptyElement(xmlDocWalkerPtr iter)
{
if ((iter == 0) || (iter->node == 0))
return(-1);
if (iter->node->type != XML_ELEMENT_NODE)
return(0);
if (iter->curnode != 0)
return(0);
if (iter->node->children != 0)
return(0);
return(1);
}
/**
* xmlDocWalkerLocalName:
* @iter: the xmlDocWalkerPtr
*
* The local name of the node.
*
* Returns the local name or NULL if not available
*/
xmlChar *
xmlDocWalkerLocalName(xmlDocWalkerPtr iter)
{
xmlNodePtr node;
if ((iter == 0) || (iter->node == 0))
return(0);
if (iter->curnode != 0)
node = iter->curnode;
else
node = iter->node;
if (node->type == XML_NAMESPACE_DECL) {
xmlNsPtr ns = (xmlNsPtr) node;
if (ns->prefix == 0)
return xmlStrdup(BAD_CAST "xmlns");
else
return xmlStrdup(ns->prefix);
}
if ((node->type != XML_ELEMENT_NODE)
&& (node->type != XML_ATTRIBUTE_NODE))
return (xmlDocWalkerName(iter));
return xmlStrdup(node->name);
}
/**
* xmlDocWalkerName:
* @iter: the xmlDocWalkerPtr
*
* The qualified name of the node, equal to Prefix :LocalName.
*
* Returns the local name or NULL if not available
*/
xmlChar *
xmlDocWalkerName(xmlDocWalkerPtr iter)
{
xmlNodePtr node;
xmlChar *ret;
if ((iter == 0) || (iter->node == 0))
return(0);
if (iter->curnode != 0)
node = iter->curnode;
else
node = iter->node;
switch (node->type) {
case XML_ELEMENT_NODE:
case XML_ATTRIBUTE_NODE:
if ((node->ns == 0) || (node->ns->prefix == NULL))
return xmlStrdup(node->name);
if ((ret = xmlStrdup(node->ns->prefix)) &&
(ret = xmlStrcat(ret, BAD_CAST ":")) &&
(ret = xmlStrcat(ret, node->name)))
return ret;
if (ret)
xmlFree(ret);
return(0);
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 == 0)
return ret;
if ((ret) &&
(ret = xmlStrcat(ret, BAD_CAST ":")) &&
(ret = xmlStrcat(ret, ns->prefix)))
return ret;
if (ret)
xmlFree(ret);
return(0);
}
case XML_ELEMENT_DECL:
case XML_ATTRIBUTE_DECL:
case XML_ENTITY_DECL:
case XML_XINCLUDE_START:
case XML_XINCLUDE_END:
return(0);
}
return(0);
}
/**
* xmlDocWalkerNodeType:
* @iter: the xmlDocWalkerPtr
*
* 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
xmlDocWalkerNodeType(xmlDocWalkerPtr iter)
{
xmlNodePtr node;
if (iter == 0)
return(-1);
if (iter->curnode != 0)
node = iter->curnode;
else
node = iter->node;
if (node == 0)
return(0);
switch (node->type) {
case XML_ELEMENT_NODE:
if ((iter->state == XML_DWALK_END) ||
(iter->state == XML_DWALK_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(iter->node)) {
if (xmlNodeGetSpacePreserve(iter->node))
return XML_READER_TYPE_SIGNIFICANT_WHITESPACE;
return XML_READER_TYPE_WHITESPACE;
}
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);
}
/**
* xmlDocWalkerPrefix:
* @iter: the xmlDocWalkerPtr
*
* A shorthand reference to the namespace associated with the node.
*
* Returns the prefix or NULL if not available
*/
xmlChar *
xmlDocWalkerPrefix(xmlDocWalkerPtr iter)
{
xmlNodePtr node;
if ((iter == 0) || (iter->node == 0) || (iter->node->ns == 0))
return(0);
if (iter->curnode != NULL)
node = iter->curnode;
else
node = iter->node;
if (node->type == XML_NAMESPACE_DECL) {
xmlNsPtr ns = (xmlNsPtr) node;
if (ns->prefix == 0)
return(0);
return xmlStrdup(BAD_CAST "xmlns");
}
if ((node->type != XML_ELEMENT_NODE) &&
(node->type != XML_ATTRIBUTE_NODE))
return NULL;
if ((node->ns != 0) && (node->ns->prefix != 0))
return xmlStrdup(node->ns->prefix);
return(0);
}
/**
* xmlDocWalkerNamespaceUri:
* @iter: the xmlDocWalkerPtr
*
* The URI defining the namespace associated with the node.
*
* Returns the namespace URI or NULL if not available
*/
xmlChar *
xmlDocWalkerNamespaceUri(xmlDocWalkerPtr iter)
{
xmlNodePtr node;
if ((iter == 0) || (iter->node == 0))
return(0);
if (iter->curnode != 0)
node = iter->curnode;
else
node = iter->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(0);
if (node->ns != 0)
return xmlStrdup(node->ns->href);
return(0);
}
/**
* xmlTextReaderBaseUri:
* @iter: the xmlDocWalkerPtr
*
* The base URI of the node.
*
* Returns the base URI or NULL if not available
*/
xmlChar *
xmlDocWalkerBaseUri(xmlDocWalkerPtr iter)
{
if ((iter == 0) || (iter->node == 0))
return(0);
return xmlNodeGetBase(0, iter->node);
}
/**
* xmlDocWalkerValue:
* @iter: the xmlDocWalkerPtr
*
* Provides the text value of the node if present
*
* Returns the string or NULL if not available. The retsult must be deallocated
* with xmlFree()
*/
xmlChar *
xmlDocWalkerValue(xmlDocWalkerPtr iter)
{
xmlNodePtr node;
if ((iter == 0) || (iter->node == 0))
return(0);
if (iter->curnode != 0)
node = iter->curnode;
else
node = iter->node;
switch (node->type) {
case XML_NAMESPACE_DECL:
return xmlStrdup(((xmlNsPtr) node)->href);
case XML_ATTRIBUTE_NODE:
{
xmlAttrPtr attr = (xmlAttrPtr) node;
if (attr->parent != 0)
return xmlNodeListGetString(attr->parent->doc,
attr->children, 1);
else
return xmlNodeListGetString(0, attr->children, 1);
}
break;
case XML_TEXT_NODE:
case XML_CDATA_SECTION_NODE:
case XML_PI_NODE:
case XML_COMMENT_NODE:
if (node->content != 0)
return xmlStrdup(node->content);
default:
break;
}
return (NULL);
}
/**
* xmlDocWalkerGetAttributeNo:
* @iter: the xmlDocWalkerPtr
* @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 *
xmlDocWalkerGetAttributeNo(xmlDocWalkerPtr iter, int no)
{
xmlChar *ret;
int i;
xmlAttrPtr cur;
xmlNsPtr ns;
if ((iter == 0) || (iter->node == 0) || (iter->curnode != 0) ||
(iter->node->type != XML_ELEMENT_NODE))
return(0);
ns = iter->node->nsDef;
for (i = 0; i < no && ns != 0; i++)
ns = ns->next;
if (ns != 0)
return (xmlStrdup(ns->href));
cur = iter->node->properties;
if (cur == 0)
return(0);
for (; i < no; i++) {
cur = cur->next;
if (cur == 0)
return(0);
}
ret = xmlNodeListGetString(iter->node->doc, cur->children, 1);
if (ret == 0)
return (xmlStrdup((xmlChar *) ""));
return ret;
}
/**
* xmlDocWalkerGetAttribute:
* @iter: the xmlDocWalkerPtr
* @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 *
xmlDocWalkerGetAttribute(xmlDocWalkerPtr iter, const xmlChar * name)
{
xmlChar *prefix = 0;
xmlChar *localname;
xmlNsPtr ns;
xmlChar *ret = 0;
if ((iter == 0) || (iter->node == 0) || (iter->curnode != 0) ||
(iter->node->type != XML_ELEMENT_NODE))
return(0);
localname = xmlSplitQName2(name, &prefix);
if (localname == 0)
return xmlGetProp(iter->node, name);
ns = xmlSearchNs(iter->node->doc, iter->node, prefix);
if (ns != 0)
ret = xmlGetNsProp(iter->node, localname, ns->href);
if (localname != 0)
xmlFree(localname);
if (prefix != 0)
xmlFree(prefix);
return ret;
}
/**
* xmlDocWalkerGetAttributeNs:
* @iter: the xmlDocWalkerPtr
* @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 *
xmlDocWalkerGetAttributeNs(xmlDocWalkerPtr iter,
const xmlChar * localName,
const xmlChar * namespaceURI)
{
if ((iter == 0) || (iter->node == 0)
|| (iter->node->type != XML_ELEMENT_NODE))
return(0);
return xmlGetNsProp(iter->node, localName, namespaceURI);
}
/**
* xmlDocWalkerLookupNamespace:
* @iter: the xmlDocWalkerPtr
* @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 *
xmlDocWalkerLookupNamespace(xmlDocWalkerPtr iter, const xmlChar * prefix)
{
xmlNsPtr ns;
if ((iter == 0) || (iter->node == 0))
return(0);
ns = xmlSearchNs(iter->node->doc, iter->node, prefix);
if (ns == NULL)
return (NULL);
return (xmlStrdup(ns->href));
}
/**
* xmlDocWalkerMoveToAttributeNo:
* @iter: the xmlDocWalkerPtr
* @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
xmlDocWalkerMoveToAttributeNo(xmlDocWalkerPtr iter, int no)
{
int i;
xmlAttrPtr cur;
xmlNsPtr ns;
if ((iter == 0) || (iter->node == 0))
return(-1);
if ((iter->state == XML_DWALK_NONE) ||
(iter->state == XML_DWALK_BACKTRACK) ||
(iter->state == XML_DWALK_END))
return(0);
if (iter->node->type != XML_ELEMENT_NODE)
return(0);
iter->curnode = NULL;
ns = iter->node->nsDef;
for (i = 0; i < no && ns != NULL; i++)
ns = ns->next;
if (ns != 0) {
iter->curnode = (xmlNodePtr) ns;
return(1);
}
cur = iter->node->properties;
if (cur == 0)
return(0);
for (; i < no; i++) {
cur = cur->next;
if (cur == 0)
return(0);
}
iter->curnode = (xmlNodePtr) cur;
return(1);
}
/**
* xmlDocWalkerMoveToAttribute:
* @iter: the xmlDocWalkerPtr
* @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
xmlDocWalkerMoveToAttribute(xmlDocWalkerPtr iter, const xmlChar * name)
{
xmlChar *prefix = NULL;
xmlChar *localname = NULL;
xmlNsPtr ns;
xmlAttrPtr prop;
int ret = 0;
if ((iter == 0) || (iter->node == 0) || (name == 0))
return(-1);
if ((iter->state == XML_DWALK_NONE) ||
(iter->state == XML_DWALK_BACKTRACK) ||
(iter->state == XML_DWALK_END))
goto not_found;
if (iter->node->type != XML_ELEMENT_NODE)
goto not_found;
localname = xmlSplitQName2(name, &prefix);
if (localname == 0) {
if (xmlStrEqual(name, BAD_CAST "xmlns")) {
ns = iter->node->nsDef;
while (ns != 0) {
if (ns->prefix == 0) {
iter->curnode = (xmlNodePtr) ns;
goto found;
}
ns = ns->next;
}
goto not_found;
}
prop = iter->node->properties;
while (prop != 0) {
if (xmlStrEqual(prop->name, name) &&
((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
iter->curnode = (xmlNodePtr) prop;
goto found;
}
prop = prop->next;
}
goto not_found;
}
if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
ns = iter->node->nsDef;
while (ns != 0) {
if (ns->prefix != NULL && xmlStrEqual(ns->prefix, localname)) {
iter->curnode = (xmlNodePtr) ns;
goto found;
}
ns = ns->next;
}
goto not_found;
}
prop = iter->node->properties;
while (prop != NULL) {
if (xmlStrEqual(prop->name, localname) &&
(prop->ns != NULL) && xmlStrEqual(prop->ns->prefix, prefix)) {
iter->curnode = (xmlNodePtr) prop;
goto found;
}
prop = prop->next;
}
if (0)
found:{
ret = 1;
}
not_found:
if (localname != 0)
xmlFree(localname);
if (prefix != 0)
xmlFree(prefix);
return ret;
}
/**
* xmlDocWalkerMoveToAttributeNs:
* @iter: the xmlDocWalkerPtr
* @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
xmlDocWalkerMoveToAttributeNs(xmlDocWalkerPtr iter,
const xmlChar * localName,
const xmlChar * namespaceURI)
{
xmlAttrPtr prop;
xmlNodePtr node;
if ((iter == 0) || (iter->node == 0) || (localName == 0)
|| (namespaceURI == 0))
return(-1);
if ((iter->state == XML_DWALK_NONE) ||
(iter->state == XML_DWALK_BACKTRACK) ||
(iter->state == XML_DWALK_END))
return(0);
if (iter->node->type != XML_ELEMENT_NODE)
return(0);
node = iter->node;
prop = node->properties;
while (prop != NULL) {
if (xmlStrEqual(prop->name, localName) &&
((prop->ns != NULL)
&& (xmlStrEqual(prop->ns->href, namespaceURI)))) {
iter->curnode = (xmlNodePtr) prop;
return(1);
}
prop = prop->next;
}
return(0);
}
/**
* xmlDocWalkerMoveToFirstAttribute:
* @iter: the xmlDocWalkerPtr
*
* 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
xmlDocWalkerMoveToFirstAttribute(xmlDocWalkerPtr iter)
{
if ((iter == 0) || (iter->node == 0))
return(-1);
if ((iter->state == XML_DWALK_NONE) ||
(iter->state == XML_DWALK_BACKTRACK) ||
(iter->state == XML_DWALK_END))
return(0);
if (iter->node->type != XML_ELEMENT_NODE)
return(0);
if (iter->node->nsDef != NULL) {
iter->curnode = (xmlNodePtr) iter->node->nsDef;
return(1);
}
if (iter->node->properties != NULL) {
iter->curnode = (xmlNodePtr) iter->node->properties;
return(1);
}
return(0);
}
/**
* xmlDocWalkerMoveToNextAttribute:
* @iter: the xmlDocWalkerPtr
*
* 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
xmlDocWalkerMoveToNextAttribute(xmlDocWalkerPtr iter)
{
if ((iter == 0) || (iter->node == 0))
return(-1);
if ((iter->state == XML_DWALK_NONE) ||
(iter->state == XML_DWALK_BACKTRACK) ||
(iter->state == XML_DWALK_END))
return(0);
if (iter->node->type != XML_ELEMENT_NODE)
return(0);
if (iter->curnode == NULL)
return (xmlDocWalkerMoveToFirstAttribute(iter));
if (iter->curnode->type == XML_NAMESPACE_DECL) {
xmlNsPtr ns = (xmlNsPtr) iter->curnode;
if (ns->next != NULL) {
iter->curnode = (xmlNodePtr) ns->next;
return(1);
}
if (iter->node->properties != NULL) {
iter->curnode = (xmlNodePtr) iter->node->properties;
return(1);
}
return(0);
} else if ((iter->curnode->type == XML_ATTRIBUTE_NODE) &&
(iter->curnode->next != NULL)) {
iter->curnode = iter->curnode->next;
return(1);
}
return(0);
}
/**
* xmlDocWalkerMoveToElement:
* @iter: the xmlDocWalkerPtr
*
* 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
xmlDocWalkerMoveToElement(xmlDocWalkerPtr iter)
{
if ((iter == 0) || (iter->node == 0))
return(-1);
if ((iter->state == XML_DWALK_NONE) ||
(iter->state == XML_DWALK_BACKTRACK) ||
(iter->state == XML_DWALK_END))
return(0);
if (iter->node->type != XML_ELEMENT_NODE)
return(0);
if (iter->curnode != NULL) {
iter->curnode = NULL;
return(1);
}
return(0);
}
/**
* xmlDocWalkerCurrentNode:
* @iter: the xmlDocWalkerPtr
*
* Hacking interface allowing to get the xmlNodePtr correponding to the
* current node being accessed by the xmlDocWalker.
*
* Returns the xmlNodePtr or NULL in case of error.
*/
xmlNodePtr
xmlDocWalkerCurrentNode(xmlDocWalkerPtr iter)
{
if (iter == 0)
return(0);
if (iter->curnode != NULL)
return iter->curnode;
return iter->node;
}
/**
* xmlDocWalkerCurrentDoc:
* @iter: the xmlDocWalkerPtr
*
* Hacking interface allowing to get the xmlDocPtr correponding to the
* current document being accessed by the xmlDocWalker.
*
* Returns the xmlDocPtr or NULL in case of error.
*/
xmlDocPtr
xmlDocWalkerCurrentDoc(xmlDocWalkerPtr iter)
{
if (iter == 0)
return(0);
return iter->doc;
}
/**
* xmlDocWalkerNext:
* @iter: the xmlDocWalkerPtr
*
* Step to the next sibling of the current node in document order
*
* Returns 1 if ok, 0 if there are no more nodes, or -1 in case of error
*/
int
xmlDocWalkerNext(xmlDocWalkerPtr iter)
{
if ((iter == 0) || (iter->doc == 0))
return(-1);
if (iter->state == XML_DWALK_END)
return(0);
if (iter->node == 0)
return xmlDocWalkerStep(iter);
if (iter->node->next != 0) {
iter->node = iter->node->next;
iter->state = XML_DWALK_START;
return(1);
}
return(0);
}
#endif /* LIBXML_WALKER_ENABLED */