/*
* Created on 02.12.2003
*
* (c) Stabsstelle IKT-Strategie des Bundes
*/
package at.gv.egovernment.moa.ss.erechtclient.util;
import java.util.HashMap;
import java.util.StringTokenizer;
import org.apache.xml.utils.PrefixResolverDefault;
import org.apache.xpath.XPath;
import org.apache.xpath.XPathContext;
import org.apache.xpath.objects.XObject;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* @author Gregor Karlinger (mailto:gregor.karlinger@cio.gv.at)
*/
public class XPathUtils
{
/**
* The XPath context for the XPath engine.
*/
protected XPathContext xPathContext_;
/**
* The prefix resolver for the XPath engine.
*/
protected PrefixResolver prefixResolver_;
/**
* The XPath engine.
*/
protected XPath xPath_;
/* ==================================================================================================== */
public void setupContext(String xPathExpr, Node namespaceNode, String additionalNSPrefixes)
throws Exception
{
try
{
// Set up a new evaluation context
xPathContext_ = new XPathContext();
// Set up the namespace prefix resolver for the XPath engine
prefixResolver_ = new PrefixResolver(namespaceNode, additionalNSPrefixes);
// Initialize XPath engine
xPath_ = new XPath(xPathExpr, null, prefixResolver_, XPath.SELECT, null);
}
catch (Exception e)
{
throw new Exception("Setting up XPath evaluation context failed.", e);
}
}
/* ---------------------------------------------------------------------------------------------------- */
public NodeList selectNodeSet(Node contextNode) throws Exception
{
XObject xObject;
try
{
xObject = xPath_.execute(xPathContext_, contextNode, prefixResolver_);
return xObject.nodelist();
}
catch (Exception e)
{
throw new Exception("Executing XPath expression failed.", e);
}
}
/* ---------------------------------------------------------------------------------------------------- */
public boolean selectBoolean(Node contextNode) throws Exception
{
XObject xObject;
try
{
xObject = xPath_.execute(xPathContext_, contextNode, prefixResolver_);
return xObject.bool();
}
catch (Exception e)
{
throw new Exception("Executing XPath expression failed.", e);
}
}
/* ==================================================================================================== */
/**
* Special extension of the {@link org.apache.xml.utils.PrefixResolverDefault} interface. Used to
* configure the Apache Xalan XPath engine which is employed as the backbone of this class.
*/
protected class PrefixResolver extends PrefixResolverDefault
{
/**
* Contains the additionally specified namespace prefix (key) to namespace URI (value) attributions.
*/
protected HashMap additionalNSPrefixesMap_;
/* ================================================================================================== */
/**
* Basic constructor.
*
* @param xpathExpressionContext The namespace declarations in scope for this node will be used to get
* the namespace uri for a prefix specified in the XPath expression.
*
* @param additionalNSPrefixes Allows the specification of additional prefix to uri attributions apart
* from the declarations in scope for the parameter
* xpathExpressionContext
. May be null
.
*/
public PrefixResolver(Node xpathExpressionContext, String additionalNSPrefixes) throws Exception
{
super(xpathExpressionContext);
additionalNSPrefixesMap_ = new HashMap();
// Register the specified additional namespace prefix to namespace uri attributions
if (additionalNSPrefixes != null)
{
StringTokenizer tokenizer = new StringTokenizer(additionalNSPrefixes, " ");
while (tokenizer.hasMoreTokens())
{
String prefix = tokenizer.nextToken();
if (!tokenizer.hasMoreTokens())
{
// There must be an even number of tokens in the string
throw new Exception("Parameter \"additionalNSPrefixes\" must have an even number of tokens.");
}
String uri = tokenizer.nextToken();
additionalNSPrefixesMap_.put(prefix, uri);
}
}
}
/* -------------------------------------------------------------------------------------------------- */
/**
* Gets the namespace uri for the specified namespace prefix. The additionally specified prefixes
* overrule the prefixes found in the specified namespace node.
*
* @param prefix The namespace prefix for which a namespace uri should be found.
*
* @return the namespace uri for the specified namespace prefix.
*/
public String getNamespaceForPrefix(String prefix)
{
String additionalURI = (String) additionalNSPrefixesMap_.get(prefix);
return (additionalURI != null)
? additionalURI
: super.getNamespaceForPrefix(prefix);
}
}
}