You need to create an instance of XPathVariableResolver and attach it to your XPath instance. There are unfortunately no standard implementations of this interface provided by default but it only contains one method so it's easy enough to implement yourself:
final Map<String, Object> variables = new HashMap<String, Object>();
XPathVariableResolver varResolver = new XPathVariableResolver() {
public Object resolveVariable(QName name) {
// for simplicity, ignore namespaces
return variables.get(name.getLocalPart());
}
};
xpath.setXPathVariableResolver(varResolver);
With this in place you can now create variable bindings and refer to them in the XPath using $var syntax:
variables.put("theName", "happy");
Node theNode2 = (Node) xpath.evaluate("//*[@name=$theName]", document2, XPathConstants.NODE);
This is much safer than trying to build up the XPath expression by concatenating different strings together, particularly if the value you want to use for theName comes from an untrusted source (this is the XPath equivalent of an SQL injection vulnerability).
For XPath there's the additional complication that while you can delimit a string literal with either single or double quotes there is no escaping mechanism, so it is impossible to have a single string literal in XPath that includes both single and double quote characters (you have to use a workaround like concat('"', "'")). The variable resolver approach can handle this situation no problem:
variables.put("theName", "John \"The Boss\" O'Brien"); // escape " from Java
Node theNode2 = (Node) xpath.evaluate("//*[@name=$theName]", document2, XPathConstants.NODE);
Furthermore, now the actual XPath expression is a constant you can compile it once and then execute it multiple times against different variable values if you need to, rather than recompile it every time:
XPathExpression expr = xpath.compile("//*[@name=$theName]");
// look for @name='name 1'
variables.put("theName", "name 1");
Node node1 = expr.evaluate(document2, XPathConstants.NODE);
// look for @name='name 2' in the same document
variables.put("theName", "name 2");
Node node2 = expr.evaluate(document2, XPathConstants.NODE);