Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xpath, Java and variables

Tags:

java

xml

xpath

Here is the code I currently have:

Document document2 = builder.parse(new FileInputStream("C:path to xml file.xml"));
Node theNode2 = (Node) xpath.evaluate("//*[@name='**variable here**']", document2, XPathConstants.NODE);

Where the code says "variable here", is it possible to search the XML file with a variable? I've only been able to hardcode in the thing I'm searching for so far ie :

("//*[@name='happy']", document2, XPathConstants.NODE);
like image 816
AJStyles Avatar asked Jun 26 '26 13:06

AJStyles


1 Answers

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);
like image 110
Ian Roberts Avatar answered Jun 29 '26 03:06

Ian Roberts



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!