Is it possible to parameterize a compiled Java XPath ala PreparedStatement expression in semantics?

Is it possible with the JAX-P xpath expression engine or another compatible mechanism to compile an xpath expression that allows parameterization?

I am looking to see if there is, if there is an API that will allow the developer to set placeholders in the compiled xpath and replace these values ​​at runtime.

Any understanding of this question about whether it is possible or not, and if there are reservations, pitfalls or just a simple β€œdo not do it” advice, we will be very grateful.

(Note that I fixed the "thread intersection" ... had a conversation with a colleague regarding xpath and regular expressions ... it just happened that the mental language is attached ... sorry for the confusion)

+5
source share
3 answers

I'm not quite sure where "regex" fits into your question.

The JAXP API allows an XPath expression to contain variables (for example, //emp[ssn=$e]), and variable values ​​are obtained at run time by calling VariableResolver, which you supply as part of the API. The JAXP specification is pretty loose as to which values ​​are acceptable, and this can vary from one implementation to another.

The Saxon XPath API (s9api) does this additionally and allows you to explicitly declare variables and their types during compilation of the expression, and then provide values ​​for the variables (of any type of XPath 2.0) when the expression is executed.

+4
source

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
+7

AFAIK, no. , String.format().

But in this way, you cannot compile it once as a parameterized xpath expr, and that is what I think you want (and what I also wanted).

+1
source

All Articles