Skip to Content.
Sympa Menu

xom-interest - Patched DocumentNavigator (was [XOM-interest] XPath support for XOM)

xom-interest AT lists.ibiblio.org

Subject: XOM API for Processing XML with Java

List archive

Chronological Thread  
  • From: Laurent Bihanic <laurent.bihanic AT atosorigin.com>
  • To: XOM-interest <XOM-interest AT lists.ibiblio.org>
  • Subject: Patched DocumentNavigator (was [XOM-interest] XPath support for XOM)
  • Date: Fri, 07 Feb 2003 11:18:06 +0100


Hi,

Please find attached a patched version of DocumentNavigator (XPath support for XOM based on Jaxen) that fixes some potential namespace handling bug. I don't know what the actual bug effects are as it never appeared in my tests (I found the problem while reviewing the code).

Laurent

Laurent Bihanic wrote:
Hi,

Attached are 2 classes that add XPath support to XOM using the Jaxen path
engine (1.0 FCS). I ran quick tests including tests on XPath functions and
namespace support and so far everything seems OK.

I put these classes in a package nu.xom.xpath.jaxen thinking XOM should wrap
them into an engine-independent XPath class, the way JDOM does. Opinions?

Laurent
/*
 */

package nu.xom.xpath.jaxen;


import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;

import org.jaxen.XPath;
import org.jaxen.DefaultNavigator;
import org.jaxen.FunctionCallException;
import org.jaxen.util.SingleObjectIterator;
import org.saxpath.SAXPathException;

import nu.xom.Attribute;
import nu.xom.Comment;
import nu.xom.Document;
import nu.xom.Element;
import nu.xom.Node;
import nu.xom.ParentNode;
import nu.xom.ProcessingInstruction;
import nu.xom.Text;
import nu.xom.Builder;


/**
 * Class for navigating around the XOM object model.
 * <p>
 * This class is not intended for direct usage, but is used by the
 * Jaxen engine during XPath expression evaluation.</p>
 */
public class DocumentNavigator extends DefaultNavigator {

    /**
     * Singleton implementation.
     */
    private static class Singleton {
        /**
         * Singleton instance.
         */
        private static DocumentNavigator instance = new DocumentNavigator();
    }

    public static DocumentNavigator getInstance() {
        return Singleton.instance;
    }

    public boolean isElement(Object obj) {
        return obj instanceof Element;
    }

    public boolean isComment(Object obj) {
        return obj instanceof Comment;
    }

    public boolean isText(Object obj) {
        return obj instanceof Text;
    }

    public boolean isAttribute(Object obj) {
        return obj instanceof Attribute;
    }

    public boolean isProcessingInstruction(Object obj) {
        return obj instanceof ProcessingInstruction;
    }

    public boolean isDocument(Object obj) {
        return obj instanceof Document;
    }

    public boolean isNamespace(Object obj) {
        return obj instanceof XPathNamespace;
    }

    public String getElementName(Object obj) {
        return ((Element)obj).getLocalName();
    }

    public String getElementNamespaceUri(Object obj) {
        String uri = ((Element)obj).getNamespaceURI();

        return ((uri != null) && (uri.length() == 0))? null: uri;
    }

    public String getAttributeName(Object obj) {
        return ((Attribute)obj).getLocalName();
    }

    public String getAttributeNamespaceUri(Object obj) {
        String uri = ((Attribute)obj).getNamespaceURI();

        return ((uri != null) && (uri.length() == 0))? null: uri;
    }

    public Iterator getChildAxisIterator(Object contextNode) {
        if (contextNode instanceof ParentNode) {
            ParentNode e = (ParentNode)contextNode;

            int  max     = e.getChildCount();
            List content = new ArrayList(max);
            for (int i=0; i<max; i++) {
                content.add(e.getChild(i));
            }
            return content.iterator();
        }
        return null;
    }

    public Iterator getNamespaceAxisIterator(Object contextNode) {
        if (contextNode instanceof Element == false) {
            return null;
        }

        Map nsMap = new HashMap();

        Element context = (Element)contextNode;
        Element current = context;

        while (current != null) {
            String prefix;

            String uri = current.getNamespaceURI();
            if (uri.length() != 0) {
                prefix = current.getNamespacePrefix();

                if (!nsMap.containsKey(prefix)) {
                    nsMap.put(prefix,
                              new XPathNamespace(context, prefix, uri));
                }
            }

            int max = current.getNamespaceDeclarationCount();
            for (int i=0; i<max; i++) {
                prefix = current.getNamespacePrefix(i);

                if (!nsMap.containsKey(prefix)) {
                    nsMap.put(prefix,
                              new XPathNamespace(context, prefix,
                                        current.getNamespaceURI(prefix)));
                }
            }
            ParentNode parent = current.getParent();
            current = (parent instanceof Element)? (Element)parent: null;
        }
        nsMap.put("xml", new XPathNamespace(context,
                            "xml", "http://www.w3.org/XML/1998/namespace";));

        return nsMap.values().iterator();
    }

    public Iterator getParentAxisIterator(Object contextNode) {
        Object parent = null;

        if (contextNode instanceof Node) {
            parent = ((Node)contextNode).getParent();
        }
        else if (contextNode instanceof XPathNamespace) {
            parent = ((XPathNamespace)contextNode).getElement();
        }

        if (parent != null) {
            return new SingleObjectIterator(parent);
        }
        return null;
    }

    public Iterator getAttributeAxisIterator(Object contextNode) {
        if (contextNode instanceof Element) {
            Element e = (Element)contextNode;

            int  max   = e.getAttributeCount();
            List attrs = new ArrayList(max);
            for (int i=0; i<max; i++) {
                attrs.add(e.getAttribute(i));
            }
            return attrs.iterator();
        }
        return null;
    }

    /**
     * Returns a parsed form of the given xpath string, which will
     * be suitable for queries on XOM documents.
     */
    public XPath parseXPath(String xpath) throws SAXPathException {
        return new XOMXPath(xpath);
    }

    public Object getDocumentNode(Object contextNode) {
        if (contextNode instanceof Node) {
            return ((Node)contextNode).getDocument();
        }
        return null;
    }

    public String getElementQName(Object obj) {
        return ((Element)obj).getQualifiedName();
    }

    public String getAttributeQName(Object obj) {
        return ((Attribute)obj).getQualifiedName();
    }

    public String getNamespaceStringValue(Object obj) {
        return ((XPathNamespace)obj).getURI();
    }

    public String getNamespacePrefix(Object obj) {
        return ((XPathNamespace)obj).getPrefix();
    }

    public String getTextStringValue(Object obj) {
        if (obj instanceof Text) {
            return ((Text)obj).getValue();
        }
        return "";
    }

    public String getAttributeStringValue(Object obj) {
        return ((Attribute)obj).getValue();
    }

    public String getElementStringValue(Object obj) {
        return ((Element)obj).getValue();
    }

    public String getProcessingInstructionTarget(Object obj) {
        return ((ProcessingInstruction)obj).getTarget();
    }

    public String getProcessingInstructionData(Object obj) {
        return ((ProcessingInstruction)obj).getValue();
    }

    public String getCommentStringValue(Object obj) {
        return ((Comment)obj).getValue();
    }

    public String translateNamespacePrefixToUri(String prefix, Object context)
    {
        Element element = null;

        if (context instanceof Element) {
            element = (Element)context;
        }
        else if (context instanceof Node) {
            Node parent = ((Node)context).getParent();
            if (parent instanceof Element) {
               element = (Element)context;
            }
        }
        else if (context instanceof XPathNamespace) {
            element = ((XPathNamespace)context).getElement();
        }

        if ( element != null ) {
            String uri = element.getNamespaceURI(prefix);
            if (uri.length() != 0) {
                return uri;
            }
        }
        return null;
    }

    public Object getDocument(String url) throws FunctionCallException {
        try {
            return new Builder().build(url);
        }
        catch (Exception e) {
            throw new FunctionCallException(e.getMessage());
        }
    }


    private static class XPathNamespace {
        /** * The XOM element to which the namespace is attached.  */
        private Element element;

        /** * The namespace prefix.  */
        private String  prefix;

        /** * The namespace URI.  */
        private String  uri;

        /**
         * Creates a namespace-node wrapper for a namespace node
         * assigned to the given element.
         */
        public XPathNamespace(Element element, String prefix, String uri)
        {
            this.element = element;
            this.prefix  = prefix;
            this.uri     = uri;
        }

        /**
         * Returns the element from which this namespace node has
         * been retrieved.  The result may be null when the namespace
         * node has not yet been assigned to an element.
         *
         * @return the element from which this namespace node has
         *         been retrieved.
         */
        public Element getElement()
        {
            return this.element;
        }

        /**
         * Returns the namespace prefix of this namespace node.
         *
         * @return the namespace prefix of this namespace node.
         */
        public String getPrefix()
        {
            return this.prefix;
        }

        /**
         * Returns the namespace URI of this namespace node.
         *
         * @return the namespace URI of this namespace node.
         */
        public String getURI()
        {
            return this.uri;
        }

        public String toString()
        {
            return ("[xmlns:" + this.getPrefix() + "=\"" +
                    this.getURI() + "\", element=" +
                    this.getElement().getLocalName() + "]" );
        }
    }
}



  • Patched DocumentNavigator (was [XOM-interest] XPath support for XOM), Laurent Bihanic, 02/07/2003

Archive powered by MHonArc 2.6.24.

Top of Page