package at.gv.egovernment.moa.util;
import java.util.List;
import java.util.Map;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.traversal.NodeIterator;
import org.jaxen.JaxenException;
import org.jaxen.NamespaceContext;
import org.jaxen.SimpleNamespaceContext;
import org.jaxen.dom.DOMXPath;
import org.jaxen.dom.DocumentNavigator;
/**
* Utility methods to evaluate XPath expressions on DOM nodes.
*
* @author Patrick Peck
* @version $Id$
*/
public class XPathUtils {
/**
* The XPath expression selecting all nodes under a given root (including the
* root node itself).
*/
public static final String ALL_NODES_XPATH =
"(.//. | .//@* | .//namespace::*)";
/** The DocumentNavigator
to use for navigating the document. */
private static DocumentNavigator documentNavigator =
DocumentNavigator.getInstance();
/** The default namespace prefix to namespace URI mappings. */
private static NamespaceContext NS_CONTEXT;
static {
SimpleNamespaceContext ctx = new SimpleNamespaceContext();
ctx.addNamespace(Constants.MOA_PREFIX, Constants.MOA_NS_URI);
ctx.addNamespace(Constants.MOA_CONFIG_PREFIX, Constants.MOA_CONFIG_NS_URI);
ctx.addNamespace(
Constants.MOA_ID_CONFIG_PREFIX,
Constants.MOA_ID_CONFIG_NS_URI);
ctx.addNamespace(Constants.SL10_PREFIX, Constants.SL10_NS_URI);
ctx.addNamespace(Constants.SL11_PREFIX, Constants.SL11_NS_URI);
ctx.addNamespace(Constants.ECDSA_PREFIX, Constants.ECDSA_NS_URI);
ctx.addNamespace(Constants.PD_PREFIX, Constants.PD_NS_URI);
ctx.addNamespace(Constants.SAML_PREFIX, Constants.SAML_NS_URI);
ctx.addNamespace(Constants.SAMLP_PREFIX, Constants.SAMLP_NS_URI);
ctx.addNamespace(Constants.DSIG_PREFIX, Constants.DSIG_NS_URI);
ctx.addNamespace(Constants.XSLT_PREFIX, Constants.XSLT_NS_URI);
ctx.addNamespace(Constants.XSI_PREFIX, Constants.XSI_NS_URI);
ctx.addNamespace(
Constants.DSIG_FILTER2_PREFIX,
Constants.DSIG_FILTER2_NS_URI);
ctx.addNamespace(Constants.DSIG_EC_PREFIX, Constants.DSIG_EC_NS_URI);
NS_CONTEXT = ctx;
}
/**
* Return a NodeIterator
over the nodes matching the XPath
* expression.
*
* All namespace URIs and prefixes declared in the Constants
* interface are used for resolving namespaces.
*
* @param contextNode The root node from which to evaluate the XPath
* expression.
* @param exp The XPath expression to evaluate.
* @return An iterator over the resulting nodes.
* @throws XPathException An error occurred evaluating the XPath expression.
*/
public static NodeIterator selectNodeIterator(Node contextNode, String exp)
throws XPathException {
return selectNodeIterator(contextNode, NS_CONTEXT, exp);
}
/**
* Return a NodeIterator
over the nodes matching the XPath
* expression.
*
* @param contextNode The root node from which to evaluate the XPath
* expression.
* @param namespaceElement An element from which to build the
* namespace mapping for evaluating the XPath expression
* @param exp The XPath expression to evaluate.
* @return An iterator over the resulting nodes.
* @throws XPathException An error occurred evaluating the XPath expression.
*/
public static NodeIterator selectNodeIterator(
Node contextNode,
Element namespaceElement,
String exp)
throws XPathException {
try {
SimpleNamespaceContext ctx = new SimpleNamespaceContext();
ctx.addElementNamespaces(documentNavigator, namespaceElement);
return selectNodeIterator(contextNode, ctx, exp);
} catch (JaxenException e) {
MessageProvider msg = MessageProvider.getInstance();
String message = msg.getMessage("xpath.00", new Object[] { exp });
throw new XPathException(message, e);
}
}
/**
* Return a NodeIterator
over the nodes matching the XPath
* expression.
*
* @param contextNode The root node from which to evaluate the XPath
* expression.
* @param namespaceMapping A namespace prefix to namespace URI mapping
* (String
to String
) for evaluating the XPath
* expression.
* @param exp The XPath expression to evaluate.
* @return An iterator over the resulting nodes.
* @throws XPathException An error occurred evaluating the XPath expression.
*/
public static NodeIterator selectNodeIterator(
Node contextNode,
Map namespaceMapping,
String exp)
throws XPathException {
SimpleNamespaceContext ctx = new SimpleNamespaceContext(namespaceMapping);
return selectNodeIterator(contextNode, ctx, exp);
}
/**
* Return a NodeIterator
over the nodes matching the XPath
* expression.
*
* @param contextNode The root node from which to evaluate the XPath
* expression.
* @param nsContext The NamespaceContext
for resolving namespace
* prefixes to namespace URIs for evaluating the XPath expression.
* @param exp The XPath expression to evaluate.
* @return An iterator over the resulting nodes.
* @throws XPathException An error occurred evaluating the XPath expression.
*/
private static NodeIterator selectNodeIterator(
Node contextNode,
NamespaceContext nsContext,
String exp)
throws XPathException {
try {
DOMXPath xpath = new DOMXPath(exp);
List nodes;
xpath.setNamespaceContext(nsContext);
nodes = xpath.selectNodes(contextNode);
return new NodeIteratorAdapter(nodes.listIterator());
} catch (JaxenException e) {
MessageProvider msg = MessageProvider.getInstance();
String message = msg.getMessage("xpath.00", new Object[] { exp });
throw new XPathException(message, e);
}
}
/**
* Return a NodeList
of all the nodes matching the XPath
* expression.
*
* All namespace URIs and prefixes declared in the Constants
* interface are used for resolving namespaces.
*
* @param contextNode The root node from which to evaluate the XPath
* expression.
* @param exp The XPath expression to evaluate.
* @return A NodeList
containing the matching nodes.
* @throws XPathException An error occurred evaluating the XPath expression.
*/
public static NodeList selectNodeList(Node contextNode, String exp)
throws XPathException {
return selectNodeList(contextNode, NS_CONTEXT, exp);
}
/**
* Return a NodeList
of all the nodes matching the XPath
* expression.
*
* @param contextNode The root node from which to evaluate the XPath
* expression.
* @param namespaceElement An element from which to build the
* namespace mapping for evaluating the XPath expression
* @param exp The XPath expression to evaluate.
* @return A NodeList
containing the matching nodes.
* @throws XPathException An error occurred evaluating the XPath expression.
*/
public static NodeList selectNodeList(
Node contextNode,
Element namespaceElement,
String exp)
throws XPathException {
try {
SimpleNamespaceContext ctx = new SimpleNamespaceContext();
ctx.addElementNamespaces(documentNavigator, namespaceElement);
return selectNodeList(contextNode, ctx, exp);
} catch (JaxenException e) {
MessageProvider msg = MessageProvider.getInstance();
String message = msg.getMessage("xpath.00", new Object[] { exp });
throw new XPathException(message, e);
}
}
/**
* Return a NodeList
of all the nodes matching the XPath
* expression.
*
* @param contextNode The root node from which to evaluate the XPath
* expression.
* @param namespaceMapping A namespace prefix to namespace URI mapping
* (String
to String
) for evaluating the XPath
* expression.
* @param exp The XPath expression to evaluate.
* @return A NodeList
containing the matching nodes.
* @throws XPathException An error occurred evaluating the XPath expression.
*/
public static NodeList selectNodeList(
Node contextNode,
Map namespaceMapping,
String exp)
throws XPathException {
SimpleNamespaceContext ctx = new SimpleNamespaceContext(namespaceMapping);
return selectNodeList(contextNode, ctx, exp);
}
/**
* Return a NodeList
of all the nodes matching the XPath
* expression.
*
* @param contextNode The root node from which to evaluate the XPath
* expression.
* @param nsContext The NamespaceContext
for resolving namespace
* prefixes to namespace URIs for evaluating the XPath expression.
* @param exp The XPath expression to evaluate.
* @return A NodeList
containing the matching nodes.
* @throws XPathException An error occurred evaluating the XPath expression.
*/
private static NodeList selectNodeList(
Node contextNode,
NamespaceContext nsContext,
String exp)
throws XPathException {
try {
DOMXPath xpath = new DOMXPath(exp);
List nodes;
xpath.setNamespaceContext(nsContext);
nodes = xpath.selectNodes(contextNode);
return new NodeListAdapter(nodes);
} catch (JaxenException e) {
MessageProvider msg = MessageProvider.getInstance();
String message = msg.getMessage("xpath.00", new Object[] { exp });
throw new XPathException(message, e);
}
}
/**
* Select the first node matching an XPath expression.
*
* All namespace URIs and prefixes declared in the Constants
* interface are used for resolving namespaces.
*
* @param contextNode The root node from which to evaluate the XPath
* expression.
* @param exp The XPath expression to evaluate.
* @return Node The first node matching the XPath expression, or
* null
, if no node matched.
* @throws XPathException An error occurred evaluating the XPath expression.
*/
public static Node selectSingleNode(Node contextNode, String exp)
throws XPathException {
return selectSingleNode(contextNode, NS_CONTEXT, exp);
}
/**
* Select the first node matching an XPath expression.
*
* @param contextNode The root node from which to evaluate the XPath
* expression.
* @param namespaceElement An element from which to build the
* namespace mapping for evaluating the XPath expression
* @param exp The XPath expression to evaluate.
* @return Node The first node matching the XPath expression, or
* null
, if no node matched.
* @throws XPathException An error occurred evaluating the XPath expression.
*/
public static Node selectSingleNode(
Node contextNode,
Element namespaceElement,
String exp)
throws XPathException {
try {
SimpleNamespaceContext ctx = new SimpleNamespaceContext();
ctx.addElementNamespaces(documentNavigator, namespaceElement);
return selectSingleNode(contextNode, ctx, exp);
} catch (JaxenException e) {
MessageProvider msg = MessageProvider.getInstance();
String message = msg.getMessage("xpath.00", new Object[] { exp });
throw new XPathException(message, e);
}
}
/**
* Select the first node matching an XPath expression.
*
* @param contextNode The root node from which to evaluate the XPath
* expression.
* @param namespaceMapping A namespace prefix to namespace URI mapping
* (String
to String
) for evaluating the XPath
* expression.
* @param exp The XPath expression to evaluate.
* @return Node The first node matching the XPath expression, or
* null
, if no node matched.
* @throws XPathException An error occurred evaluating the XPath expression.
*/
public static Node selectSingleNode(
Node contextNode,
Map namespaceMapping,
String exp)
throws XPathException {
SimpleNamespaceContext ctx = new SimpleNamespaceContext(namespaceMapping);
return selectSingleNode(contextNode, ctx, exp);
}
/**
* Select the first node matching an XPath expression.
*
* @param contextNode The root node from which to evaluate the XPath
* expression.
* @param nsContext The NamespaceContext
for resolving namespace
* prefixes to namespace URIs for evaluating the XPath expression.
* @param exp The XPath expression to evaluate.
* @return Node The first node matching the XPath expression, or
* null
, if no node matched.
* @throws XPathException An error occurred evaluating the XPath expression.
*/
private static Node selectSingleNode(
Node contextNode,
NamespaceContext nsContext,
String exp)
throws XPathException {
try {
DOMXPath xpath = new DOMXPath(exp);
xpath.setNamespaceContext(nsContext);
return (Node) xpath.selectSingleNode(contextNode);
} catch (JaxenException e) {
MessageProvider msg = MessageProvider.getInstance();
String message = msg.getMessage("xpath.00", new Object[] { exp });
throw new XPathException(message, e);
}
}
/**
* Return the value of a DOM element whose location is given by an XPath
* expression.
*
* @param root The root element from which to evaluate the XPath.
* @param xpath The XPath expression pointing to the element whose value
* to return.
* @param def The default value to return, if no element can be found using
* the given xpath
.
* @return The element value, if it can be located using the
* xpath
. Otherwise, def
is returned.
*/
public static String getElementValue(
Element root,
String xpath,
String def) {
Element elem = (Element) XPathUtils.selectSingleNode(root, xpath);
return elem != null ? DOMUtils.getText(elem) : def;
}
/**
* Return the value of a DOM attribute whose location is given by an XPath
* expression.
*
* @param root The root element from which to evaluate the XPath.
* @param xpath The XPath expression pointing to the attribute whose value to
* return.
* @param def The default value to return, if no attribute can be found using
* the given xpath
.
* @return The element value, if it can be located using the
* xpath
. Otherwise, def
is returned.
*/
public static String getAttributeValue(
Element root,
String xpath,
String def) {
Attr attr = (Attr) XPathUtils.selectSingleNode(root, xpath);
return attr != null ? attr.getValue() : def;
}
}