When we want to process multiple identical XPath query on XML document, in a optimized way, we have to compile only once XPath query and to store it to be able to use it later.
Le following singleton Java class manage in a simple way cached XPath query:
package com.devbypractice;
import java.util.HashMap;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class XPathProcessor
{
// Singleton instance
//
protected static XPathProcessor _instance = new XPathProcessor();
// XPath expressions hashmap cache
//
protected HashMap<String, XPathExpression> _hmXPathExpressions = new HashMap<String, XPathExpression>();
// Xpath processing object
//
XPath xPath = XPathFactory.newInstance().newXPath();
/**
* Private constructor
*/
protected XPathProcessor() {}
/**
* @return Singleton instance
*/
public static XPathProcessor getInstance()
{
return _instance;
}
/**
* Get XPath compiled expression from cache
*
* @param sXpathExpress XPath string
* @return XPath compiled expression
* @throws Exception
*/
protected XPathExpression getExpression(String sXpathExpress) throws Exception
{
XPathExpression expression;
if (_hmXPathExpressions.containsKey(sXpathExpress)) {
expression = _hmXPathExpressions.get(sXpathExpress);
}
else {
expression = xPath.compile(sXpathExpress);
_hmXPathExpressions.put(sXpathExpress, expression);
}
return expression;
}
/**
* Evaluate XPath expression on Xml with single result
* @param sXpathExpress XPath string
* @param xml XML node
* @return Single result of XPath evaluation
* @throws Exception
*/
public String Evaluate(String sXpathExpress, Node xml) throws Exception
{
XPathExpression expr = getExpression(sXpathExpress);
return expr.evaluate(xml);
}
/**
* Evaluate XPath expression on Xml with multiple results
* @param sXpathExpress XPath string
* @param xml XML node
* @return Multiple results of XPath evaluation
* @throws Exception
*/
public NodeList EvaluateMutli(String sXpathExpress, Node xml) throws Exception
{
XPathExpression expr = getExpression(sXpathExpress);
return (NodeList)expr.evaluate(xml, XPathConstants.NODESET);
}
}
Usage:
- XPathProcessor.getInstance().Evaluate(“/xpath1″, xmlNode1)
- XPathProcessor.getInstance().EvaluateMulti(“/xpath2″, xmlNode2)
Should be noted that XPathExpression is not thread safe. Approach you described will not work without synchronization, pooling, etc.
http://download.oracle.com/javase/6/docs/api/javax/xml/xpath/XPathExpression.html