Skip to Content.
Sympa Menu

xom-interest - [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: [XOM-interest] XPath support for XOM
  • Date: Thu, 30 Jan 2003 16:16:20 +0100


[Same mail but with the source code attached!]

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 org.jaxen.JaxenException;

import org.jaxen.BaseXPath;
import org.jaxen.Navigator;
import org.jaxen.XPath;


/**
 * An XPath implementation for the XOM model
 * <p>
 * This is the main entry point for matching an XPath against a XOM
 * tree.  You create a compiled XPath object, then match it against
 * one or more context nodes using the {@link #selectNodes}
 * method, as in the following example:</p>
 * <pre>
 *   Object xomNode = ...;              // Document, Element, etc.
 *   XPath  path    = new XOMXPath("a/b/c");
 *   List   results = path.selectNodes(xomNode);
 * </pre>
 *
 * @see <a href="http://jaxen.sourceforge.net/";>The Jaxen project</a>
 */
public class XOMXPath extends BaseXPath
{
    /**
     * Constructs given an XPath expression string.
     *
     * @param xpathExpr The XPath expression.
     *
     * @throws JaxenException if there is a syntax error while
     *                        parsing the expression.
     */
    public XOMXPath(String xpathExpr) throws JaxenException
    {
        super(xpathExpr, DocumentNavigator.getInstance());
    }
}

/*
 */

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 uri;
            String prefix;

            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, uri));
                }
            }
            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 JDOM 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() + "]" );
        }
    }
}




Archive powered by MHonArc 2.6.24.

Top of Page