Можно ли параметризовать скомпилированное выражение Java XPath аля семантика стиля PreparedStatement?
Возможно ли с помощью стандартного механизма выражений xpath JAX-P или другого совместимого механизма скомпилировать выражение xpath, которое позволило бы параметризоваться?
Я смотрю, есть ли API, который позволил бы разработчику устанавливать заполнители в скомпилированном xpath и заменять эти значения во время выполнения.
Любое понимание этого вопроса относительно того, возможно ли это и есть ли предостережения, подводные камни или просто совет типа "не делай этого", будет с благодарностью.
(Обратите внимание, что я исправил "пересечение потоков" ... разговаривал с коллегой по поводу xpath и регулярных выражений... только что случился мысленно привязанный язык... извините за путаницу)
3 ответа
Я не совсем уверен, где "регулярное выражение" вписывается в ваш вопрос.
JAXP API позволяет выражению XPath содержать переменные (например, //emp[ssn=$e]
), а значения переменных получаются во время выполнения путем вызова VariableResolver, который вы предоставляете как часть API. Спецификация JAXP довольно свободна в отношении того, какие значения являются приемлемыми, и это может варьироваться от одной реализации к другой.
Saxon XPath API (s9api) делает это дальше и позволяет вам явно объявлять переменные и их типы во время компиляции выражения, а затем предоставлять значения для переменных (любого типа XPath 2.0) при выполнении выражения.
Вот очень простая реализация 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);
}
}
Используйте это так:
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());
}
}
На этом документе:
<root>
<element id="1">one</element>
<element id="2">two</element>
<element id="3">three</element>
</root>
Выход:
two
AFAIK, нет. Я исследовал это некоторое время назад и в конечном итоге использовал String.format()
,
Но, таким образом, вы не сможете скомпилировать его один раз как параметризованный xpath expr, и это то, что я думаю, вы хотите (и то, что я тоже хотел).