All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.axiom.om.xpath.DocumentNavigator Maven / Gradle / Ivy

There is a newer version: 5.0.22
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.axiom.om.xpath;

import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMComment;
import org.apache.axiom.om.OMContainer;
import org.apache.axiom.om.OMDocument;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.OMNode;
import org.apache.axiom.om.OMProcessingInstruction;
import org.apache.axiom.om.OMText;
import org.apache.axiom.om.OMXMLBuilderFactory;
import org.jaxen.BaseXPath;
import org.jaxen.DefaultNavigator;
import org.jaxen.FunctionCallException;
import org.jaxen.JaxenConstants;
import org.jaxen.UnsupportedAxisException;
import org.jaxen.XPath;
import org.jaxen.saxpath.SAXPathException;
import org.jaxen.util.SingleObjectIterator;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

public class DocumentNavigator extends DefaultNavigator {

    private static final long serialVersionUID = 7325116153349780805L;

    /**
     * Returns a parsed form of the given xpath string, which will be suitable for queries on
     * documents that use the same navigator as this one.
     *
     * @param xpath the XPath expression
     * @return Returns a new XPath expression object.
     * @throws SAXPathException if the string is not a syntactically correct XPath expression
     * @see XPath
     */
    @Override
    public XPath parseXPath(String xpath) throws SAXPathException {
        return new BaseXPath(xpath, this);
    }

    /**
     * Retrieves the namespace URI of the given element node.
     *
     * @param object the context element node
     * @return Returns the namespace URI of the element node.
     */
    @Override
    public String getElementNamespaceUri(Object object) {
        OMElement attr = (OMElement) object;
        return attr.getQName().getNamespaceURI();
    }

    /**
     * Retrieves the name of the given element node.
     *
     * @param object the context element node
     * @return Returns the name of the element node.
     */
    @Override
    public String getElementName(Object object) {
        return ((OMElement) object).getLocalName();
    }

    /**
     * Retrieves the QName of the given element node.
     *
     * @param object the context element node
     * @return Returns the QName of the element node.
     */
    @Override
    public String getElementQName(Object object) {
        OMElement attr = (OMElement) object;
        String prefix = null;
        OMNamespace namespace = attr.getNamespace();
        if (namespace != null) {
            prefix = namespace.getPrefix();
        }
        if (prefix == null || "".equals(prefix)) {
            return attr.getLocalName();
        }
        return prefix + ":" + namespace.getNamespaceURI();
    }

    /**
     * Retrieves the namespace URI of the given attribute node.
     *
     * @param object the context attribute node
     * @return Returns the namespace URI of the attribute node.
     */
    @Override
    public String getAttributeNamespaceUri(Object object) {
        OMAttribute attr = (OMAttribute) object;
        return attr.getQName().getNamespaceURI();
    }

    /**
     * Retrieves the name of the given attribute node.
     *
     * @param object the context attribute node
     * @return Returns the name of the attribute node.
     */
    @Override
    public String getAttributeName(Object object) {
        return ((OMAttribute) object).getLocalName();
    }

    /**
     * Retrieves the QName of the given attribute node.
     *
     * @param object the context attribute node
     * @return Returns the qualified name of the attribute node.
     */
    @Override
    public String getAttributeQName(Object object) {
        OMAttribute attr = (OMAttribute) object;
        String prefix = attr.getNamespace().getPrefix();
        if (prefix == null || "".equals(prefix)) {
            return attr.getLocalName();
        }
        return prefix + ":" + attr.getLocalName();
    }

    /**
     * Returns whether the given object is a document node. A document node is the node that is
     * selected by the xpath expression /.
     *
     * @param object the object to test
     * @return Returns true if the object is a document node, else false
     *         .
     */
    @Override
    public boolean isDocument(Object object) {
        return object instanceof OMDocument;
    }

    /**
     * Returns whether the given object is an element node.
     *
     * @param object the object to test
     * @return Returns true if the object is an element node, else false
     *         .
     */
    @Override
    public boolean isElement(Object object) {
        return object instanceof OMElement;
    }

    /**
     * Returns whether the given object is an attribute node.
     *
     * @param object the object to test
     * @return Returns true if the object is an attribute node, else false
     *         .
     */
    @Override
    public boolean isAttribute(Object object) {
        return object instanceof OMAttribute;
    }

    /**
     * Returns whether the given object is a namespace node.
     *
     * @param object the object to test
     * @return Returns true if the object is a namespace node, else false
     *         .
     */
    @Override
    public boolean isNamespace(Object object) {
        return object instanceof OMNamespace;
    }

    /**
     * Returns whether the given object is a comment node.
     *
     * @param object the object to test
     * @return Returns true if the object is a comment node, else false .
     */
    @Override
    public boolean isComment(Object object) {
        return (object instanceof OMComment);
    }

    /**
     * Returns whether the given object is a text node.
     *
     * @param object the object to test
     * @return Returns true if the object is a text node, else false .
     */
    @Override
    public boolean isText(Object object) {
        return (object instanceof OMText);
    }

    /**
     * Returns whether the given object is a processing-instruction node.
     *
     * @param object the object to test
     * @return Returns true if the object is a processing-instruction node, else
     *         false .
     */
    @Override
    public boolean isProcessingInstruction(Object object) {
        return (object instanceof OMProcessingInstruction);
    }

    /**
     * Retrieves the string-value of a comment node. This may be the empty string if the comment is
     * empty, but must not be null.
     *
     * @param object the comment node
     * @return Returns the string-value of the node.
     */
    @Override
    public String getCommentStringValue(Object object) {
        return ((OMComment) object).getValue();
    }

    /**
     * Retrieves the string-value of an element node. This may be the empty string if the element is
     * empty, but must not be null.
     *
     * @param object the comment node.
     * @return Returns the string-value of the node.
     */
    @Override
    public String getElementStringValue(Object object) {
        if (isElement(object)) {
            return getStringValue((OMElement) object, new StringBuffer())
                    .toString();
        }
        return null;
    }

    private StringBuffer getStringValue(OMNode node, StringBuffer buffer) {
        if (isText(node)) {
            buffer.append(((OMText) node).getText());
        } else if (node instanceof OMElement) {
            Iterator children = ((OMElement) node).getChildren();
            while (children.hasNext()) {
                getStringValue(children.next(), buffer);
            }
        }
        return buffer;
    }

    /**
     * Retrieves the string-value of an attribute node. This should be the XML 1.0 normalized
     * attribute value. This may be the empty string but must not be null.
     *
     * @param object the attribute node
     * @return Returns the string-value of the node.
     */
    @Override
    public String getAttributeStringValue(Object object) {
        return ((OMAttribute) object).getAttributeValue();
    }

    /**
     * Retrieves the string-value of a namespace node. This is generally the namespace URI. This may
     * be the empty string but must not be null.
     *
     * @param object the namespace node
     * @return Returns the string-value of the node.
     */
    @Override
    public String getNamespaceStringValue(Object object) {
        return ((OMNamespace) object).getNamespaceURI();
    }

    /**
     * Retrieve the string-value of a text node. This must not be null and should not be the empty
     * string. The XPath data model does not allow empty text nodes.
     *
     * @param object the text node
     * @return Returns the string-value of the node.
     */
    @Override
    public String getTextStringValue(Object object) {
        return ((OMText) object).getText();
    }

    /**
     * Retrieves the namespace prefix of a namespace node.
     *
     * @param object the namespace node
     * @return Returns the prefix associated with the node.
     */
    @Override
    public String getNamespacePrefix(Object object) {
        return ((OMNamespace) object).getPrefix();
    }

    /**
     * Retrieves an Iterator matching the child XPath axis.
     *
     * @param contextNode the original context node
     * @return Returns an Iterator capable of traversing the axis, not null.
     * @throws UnsupportedAxisException if the semantics of the child axis are not supported by this
     *                                  object model
     */
    @Override
    public Iterator getChildAxisIterator(Object contextNode) throws UnsupportedAxisException {
        if (contextNode instanceof OMContainer) {
            return ((OMContainer) contextNode).getChildren();
        }
        return JaxenConstants.EMPTY_ITERATOR;
    }

    @Override
    public Iterator getDescendantAxisIterator(Object object) throws UnsupportedAxisException {
        //TODO: Fix this better?
        return super.getDescendantAxisIterator(object);
    }

    /**
     * Retrieves an Iterator matching the attribute XPath axis.
     *
     * @param contextNode the original context node
     * @return Returns an Iterator capable of traversing the axis, not null.
     * @throws UnsupportedAxisException if the semantics of the attribute axis are not supported by
     *                                  this object model
     */
    @Override
    public Iterator getAttributeAxisIterator(Object contextNode) throws UnsupportedAxisException {
        if (isElement(contextNode)) {
            return ((OMElement) contextNode).getAllAttributes();
        } else {
            return JaxenConstants.EMPTY_ITERATOR;
        }
    }

    /**
     * Retrieves an Iterator matching the namespace XPath axis.
     *
     * @param contextNode the original context node
     * @return Returns an Iterator capable of traversing the axis, not null.
     * @throws UnsupportedAxisException if the semantics of the namespace axis are not supported by
     *                                  this object model
     */
    @Override
    public Iterator getNamespaceAxisIterator(Object contextNode) throws UnsupportedAxisException {
        if (!(contextNode instanceof OMContainer &&
                contextNode instanceof OMElement)) {
            return JaxenConstants.EMPTY_ITERATOR;
        }
        OMContainer omContextNode = (OMContainer) contextNode;
        List nsList = new ArrayList();
        Set prefixes = new HashSet();
        for (OMContainer context = omContextNode;
             context != null && !(context instanceof OMDocument);
             context = ((OMElement) context).getParent()) {
            OMElement element = (OMElement) context;
            List declaredNS = new ArrayList();
            Iterator i = element.getAllDeclaredNamespaces();
            while (i != null && i.hasNext()) {
                declaredNS.add(i.next());
            }
            declaredNS.add(element.getNamespace());
            for (Iterator iter = element.getAllAttributes();
                 iter != null && iter.hasNext();) {
                OMAttribute attr = iter.next();
                OMNamespace namespace = attr.getNamespace();
                if (namespace != null) {
                    declaredNS.add(namespace);
                }
            }
            for (OMNamespace namespace : declaredNS) {
                if (namespace != null) {
                    String prefix = namespace.getPrefix();
                    if (prefix != null && !prefixes.contains(prefix)) {
                        prefixes.add(prefix);
                        nsList.add(new OMNamespaceEx(namespace, context));
                    }
                }
            }
        }
        nsList.add(
                new OMNamespaceEx(
                        omContextNode.getOMFactory().createOMNamespace(
                                "http://www.w3.org/XML/1998/namespace",
                                "xml"),
                        omContextNode));
        return nsList.iterator();
    }

    /**
     * Retrieves an Iterator matching the self xpath axis.
     *
     * @param contextNode the original context node
     * @return Returns an Iterator capable of traversing the axis, not null.
     * @throws UnsupportedAxisException if the semantics of the self axis are not supported by this
     *                                  object model
     */
    @Override
    public Iterator getSelfAxisIterator(Object contextNode) throws UnsupportedAxisException {
        //TODO: Fix this better?
        return super.getSelfAxisIterator(contextNode);
    }

    /**
     * Retrieves an Iterator matching the descendant-or-self XPath axis.
     *
     * @param contextNode the original context node
     * @return Returns an Iterator capable of traversing the axis, not null.
     * @throws UnsupportedAxisException if the semantics of the descendant-or-self axis are not
     *                                  supported by this object model
     */
    @Override
    public Iterator getDescendantOrSelfAxisIterator(Object contextNode)
            throws UnsupportedAxisException {
        //TODO: Fix this better?
        return super.getDescendantOrSelfAxisIterator(contextNode);
    }

    /**
     * Retrieves an Iterator matching the ancestor-or-self XPath axis.
     *
     * @param contextNode the original context node
     * @return Returns an Iterator capable of traversing the axis, not null.
     * @throws UnsupportedAxisException if the semantics of the ancestor-or-self axis are not
     *                                  supported by this object model
     */
    @Override
    public Iterator getAncestorOrSelfAxisIterator(Object contextNode)
            throws UnsupportedAxisException {
        //TODO: Fix this better?
        return super.getAncestorOrSelfAxisIterator(contextNode);
    }

    /**
     * Retrieves an Iterator matching the parent XPath axis.
     *
     * @param contextNode the original context node
     * @return Returns an Iterator capable of traversing the axis, not null.
     * @throws UnsupportedAxisException if the semantics of the parent axis are not supported by
     *                                  this object model
     */
    @Override
    public Iterator getParentAxisIterator(Object contextNode) throws UnsupportedAxisException {
        if (contextNode instanceof OMNode) {
            return new SingleObjectIterator(((OMNode) contextNode).getParent());
        } else if (contextNode instanceof OMNamespaceEx) {
            return new SingleObjectIterator(
                    ((OMNamespaceEx) contextNode).getParent());
        } else if (contextNode instanceof OMAttribute) {
            return new SingleObjectIterator(
                    ((OMAttribute) contextNode).getOwner());
        }
        return JaxenConstants.EMPTY_ITERATOR;
    }

    /**
     * Retrieves an Iterator matching the ancestor XPath axis.
     *
     * @param contextNode the original context node
     * @return Returns an Iterator capable of traversing the axis, not null.
     * @throws UnsupportedAxisException if the semantics of the ancestor axis are not supported by
     *                                  this object model
     */
    @Override
    public Iterator getAncestorAxisIterator(Object contextNode) throws UnsupportedAxisException {
        //TODO: Fix this better?
        return super.getAncestorAxisIterator(contextNode);
    }

    /**
     * Retrieves an Iterator matching the following-sibling XPath axis.
     *
     * @param contextNode the original context node
     * @return Returns an Iterator capable of traversing the axis, not null.
     * @throws UnsupportedAxisException if the semantics of the following-sibling axis are not
     *                                  supported by this object model
     */
    @Override
    public Iterator getFollowingSiblingAxisIterator(Object contextNode)
            throws UnsupportedAxisException {
        List list = new ArrayList();
        if (contextNode != null && contextNode instanceof OMNode) {
            OMNode node = (OMNode)contextNode;
            while (true) {
                node = node.getNextOMSibling();
                if (node != null) {
                    list.add(node);
                } else {
                    break;
                }
            }
        }
        return list.iterator();
    }

    /**
     * Retrieves an Iterator matching the preceding-sibling XPath axis.
     *
     * @param contextNode the original context node
     * @return Returns an Iterator capable of traversing the axis, not null.
     * @throws UnsupportedAxisException if the semantics of the preceding-sibling axis are not
     *                                  supported by this object model
     */
    @Override
    public Iterator getPrecedingSiblingAxisIterator(Object contextNode)
            throws UnsupportedAxisException {
        List list = new ArrayList();
        if (contextNode != null && contextNode instanceof OMNode) {
            OMNode node = (OMNode)contextNode;
            while (true) {
                node = node.getPreviousOMSibling();
                if (node != null) {
                    list.add(node);
                } else {
                    break;
                }
            }
        }
        return list.iterator();
    }

    /**
     * Retrieves an Iterator matching the following XPath axis.
     *
     * @param contextNode the original context node
     * @return Returns an Iterator capable of traversing the axis, not null.
     * @throws UnsupportedAxisException if the semantics of the following axis are not supported by
     *                                  this object model
     */
    @Override
    public Iterator getFollowingAxisIterator(Object contextNode) throws UnsupportedAxisException {
        //TODO: Fix this better?
        return super.getFollowingAxisIterator(contextNode);
    }

    /**
     * Retrieves an Iterator matching the preceding XPath axis.
     *
     * @param contextNode the original context node
     * @return Returns an Iterator capable of traversing the axis, not null.
     * @throws UnsupportedAxisException if the semantics of the preceding axis are not supported by
     *                                  this object model
     */
    @Override
    public Iterator getPrecedingAxisIterator(Object contextNode) throws UnsupportedAxisException {
        //TODO: Fix this better?
        return super.getPrecedingAxisIterator(contextNode);
    }

    /**
     * Loads a document from the given URI.
     *
     * @param uri the URI of the document to load
     * @return Returns the document.
     * @throws FunctionCallException if the document could not be loaded
     */
    @Override
    public Object getDocument(String uri)
            throws FunctionCallException {
        InputStream in = null;
        try {
            if (uri.indexOf(':') == -1) {
                in = new FileInputStream(uri);
            } else {
                URL url = new URL(uri);
                in = url.openStream();
            }
            return OMXMLBuilderFactory.createOMBuilder(in).getDocument();
        } catch (Exception e) {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException ex) {
                    // Ignore
                }
            }
            throw new FunctionCallException(e);
        }
    }

    /**
     * Returns the element whose ID is given by elementId. If no such element exists, returns null.
     * Attributes with the name "ID" are not of type ID unless so defined. Implementations that do
     * not know whether attributes are of type ID or not are expected to return null.
     *
     * @param contextNode a node from the document in which to look for the id
     * @param elementId   id to look for
     * @return Returns element whose ID is given by elementId, or null if no such element exists in
     *         the document or if the implementation does not know about attribute types.
     */
    @Override
    public Object getElementById(Object contextNode, String elementId) {
        //TODO: Fix this better?
        return super.getElementById(contextNode, elementId);
    }

    /**
     * Returns the document node that contains the given context node.
     *
     * @param contextNode the context node
     * @return Returns the document of the context node.
     * @see #isDocument(Object)
     */
    @Override
    public Object getDocumentNode(Object contextNode) {
        if (contextNode instanceof OMDocument) {
            return contextNode;
        }
        OMContainer parent = ((OMNode) contextNode).getParent();
        if (parent == null) {
            // this node doesn't have a parent Document. So return the document element itself
            return contextNode;
        } else {
            return getDocumentNode(parent);
        }
    }

    /**
     * Translates a namespace prefix to a namespace URI, possibly considering a particular
     * element node.
     * 

* Strictly speaking, prefix-to-URI translation should occur irrespective of any element in the * document. This method is provided to allow a non-conforming ease-of-use enhancement.

* * @param prefix the prefix to translate * @param element the element to consider during translation * @return Returns the namespace URI associated with the prefix. */ @Override public String translateNamespacePrefixToUri(String prefix, Object element) { //TODO: Fix this better? return super.translateNamespacePrefixToUri(prefix, element); } /** * Retrieves the target of a processing-instruction. * * @param object the context processing-instruction node * @return Returns the target of the processing-instruction node. */ @Override public String getProcessingInstructionTarget(Object object) { return ((OMProcessingInstruction) object).getTarget(); } /** * Retrieves the data of a processing-instruction. * * @param object the context processing-instruction node * @return Returns the data of the processing-instruction node. */ @Override public String getProcessingInstructionData(Object object) { return ((OMProcessingInstruction) object).getValue(); } /** * Returns a number that identifies the type of node that the given object represents in this * navigator. See org.jaxen.pattern.Pattern * * @param node ???? * @return Returns short. */ @Override public short getNodeType(Object node) { //TODO: Fix this better? return super.getNodeType(node); } /** * Returns the parent of the given context node. *

* The parent of any node must either be a document node or an element node. * * @param contextNode the context node * @return Returns the parent of the context node, or null if this is a document node. * @throws UnsupportedAxisException if the parent axis is not supported by the model * @see #isDocument * @see #isElement */ @Override public Object getParentNode(Object contextNode) throws UnsupportedAxisException { if (contextNode == null || contextNode instanceof OMDocument) { return null; } else if (contextNode instanceof OMAttribute) { return ((OMAttribute) contextNode).getOwner(); } else if (contextNode instanceof OMNamespaceEx) { return ((OMNamespaceEx) contextNode).getParent(); } return ((OMNode) contextNode).getParent(); } class OMNamespaceEx implements OMNamespace { final OMNamespace originalNsp; final OMContainer parent; OMNamespaceEx(OMNamespace nsp, OMContainer parent) { originalNsp = nsp; this.parent = parent; } @Override public boolean equals(String uri, String prefix) { return originalNsp.equals(uri, prefix); } @Override public String getPrefix() { return originalNsp.getPrefix(); } @Override public String getName() { return originalNsp.getNamespaceURI(); } @Override public String getNamespaceURI() { return originalNsp.getNamespaceURI(); } public OMContainer getParent() { return parent; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy