Edit

kc3-lang/libxml2/xmldwalk.c

Branch :

  • Show log

    Commit

  • Author : Daniel Veillard
    Date : 2003-10-03 23:59:20
    Hash : 1ae42d65
    Message : integrated the xmlDocWalker API given by Alfred Mickautsch, and providing * Makefile.am configure.in xmldwalk.c include/libxml/Makefile.am include/libxml/xmldwalk.h include/libxml/xmlversion.h.in: integrated the xmlDocWalker API given by Alfred Mickautsch, and providing an xmlReader like API but working on a xmlDocPtr. Daniel

  • xmldwalk.c
  • /*
     * 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 */