Is it possible either with the stock JAX-P xpath expression engine or another compliant engine to compile an xpath expression that would allow for parametrization?
I'm looking to see if is if there is an API that would allow a developer to set placeholders within a compiled xpath and replace those values at run time.
Any insight on this as to whether or not it is possible and if there are caveats, pitfalls, or just plain "don't do that" type advice would be greatly appreciated.
(Note I corrected a "crossing of the streams" ... was having a conversation with a coworker with regard to xpath & regular expressions ... just happened to get mentally tongue tied ..开发者_如何学Go. sorry for the confusion)
Here's a very simple implementation of javax.xml.xpath.XPathVariableResolver
import java.util.HashMap;
import java.util.Map;
import javax.xml.namespace.QName;
import javax.xml.xpath.XPathVariableResolver;
public class SimpleVariableResolver implements XPathVariableResolver {
private static final Map<QName, Object> vars =
new HashMap<QName, Object>();
public void addVariable(QName name, Object value) {
vars.put(name, value);
}
public Object resolveVariable(QName name) {
return vars.get(name);
}
}
Use it like this:
public static void main(String[] args) throws ParserConfigurationException,
SAXException, IOException, XPathExpressionException {
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse("workbook.xml");
XPath xpath = XPathFactory.newInstance().newXPath();
SimpleVariableResolver resolver = new SimpleVariableResolver();
resolver.addVariable(new QName(null, "id"), 2);
xpath.setXPathVariableResolver(resolver);
XPathExpression expr = xpath.compile("/root/element[@id=$id]");
Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
for (int i = 0; i < nodes.getLength(); i++) {
System.out.println(nodes.item(i).getTextContent());
}
}
On this document:
<root>
<element id="1">one</element>
<element id="2">two</element>
<element id="3">three</element>
</root>
Output:
two
I'm not quite sure where "regular expression" fits into your question.
The JAXP API allows an XPath expression to contain variables (for example //emp[ssn=$e]
), and the values of the variables are obtained at run-time by a call to the VariableResolver that you supply as part of the API. The JAXP spec is rather loose about what kind of values are acceptable and this may vary from one implementation to another.
The Saxon XPath API (s9api) takes this further and allows you to explicitly declare variables and their types at the time the expression is compiled, and then to supply values for the variables (of any XPath 2.0 type) when the expression is executed.
AFAIK, no. I researched that some time ago and ended up using String.format()
.
But, this way you wouldn't be able to compile it once as a parametrized xpath expr, and that is what I think you want (and what I wanted too).
精彩评论