2011-07-19 15 views
5

¿Es posible con el motor de expresiones JAX-P xpath o con otro motor compatible compilar una expresión xpath que permita la parametrización?¿Es posible parametrizar una expresión Java XPath compilada a nivel de semántica de estilo PreparedStatement?

Estoy buscando para ver si hay una API que permita a un desarrollador establecer marcadores de posición dentro de un xpath compilado y reemplazar esos valores en tiempo de ejecución.

Cualquier observación sobre esto, si es posible o no, y si hay advertencias, riesgos, o simplemente el tipo de consejo "no lo hagas" sería muy apreciado.

(Nota Corregí un "cruce de las corrientes" ... estaba teniendo una conversación con un compañero de trabajo con respecto a xpath & expresiones regulares ... acaba de casarse mentalmente ... perdón por la confusión)

+0

¡Guau! Gracias por las respuestas sobre esto. ¡Había pasado por alto completamente la API en esto, gracias a todos por señalar esto! –

Respuesta

4

No estoy muy seguro de qué "expresión regular" se ajusta a su pregunta.

La API JAXP permite que una expresión XPath contenga variables (por ejemplo //emp[ssn=$e]), y los valores de las variables se obtienen en tiempo de ejecución mediante una llamada al VariableResolver que usted suministra como parte de la API. La especificación JAXP es bastante flexible sobre qué tipo de valores son aceptables y esto puede variar de una implementación a otra.

La API de XPath de Saxon (s9api) lleva esto más allá y le permite declarar explícitamente variables y sus tipos en el momento en que se compila la expresión, y luego suministrar valores para las variables (de cualquier tipo XPath 2.0) cuando la expresión es ejecutado.

+0

¿podría darnos alguna muestra de código, amigo mío? – everton

+0

@Michael: disculpa por la confusión, he corregido mi pregunta eliminando el "normal" de arriba. Además, ¿puede proporcionar una pequeña muestra de código con su respuesta o un enlace a una página que lo demuestre? Me dirijo a mirar la API para verificarlo. –

1

AFAIK, no. Investigué eso hace algún tiempo y terminé usando String.format().

Pero, de esta manera, no sería capaz de compilarlo una vez como expr patpath parametrized, y eso es lo que creo que quiere (y lo que yo también quería).

+0

sí, más o menos para lo que estaba intentando ... bueno. –

7

Aquí hay una aplicación muy sencilla de 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); 
    } 

} 

utilizar de esta manera:

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()); 
    } 
} 

En este documento:

<root> 
    <element id="1">one</element> 
    <element id="2">two</element> 
    <element id="3">three</element> 
</root> 

Salida:

two 
+0

¡Gracias por publicar esto también! Estaba implementando esto más o menos de la misma manera después de leer la API. –

+0

Me gusta la respuesta de @everton-agner y la voté. Esta respuesta muestra un excelente ejemplo de código, pero creo que las sutilezas son 1) 'xpath.compile' debe llamarse para cada sustitución de variable, después de' xpath.setXPathVariableResolver' y 2) 'XPathVariableResolver' menciona que los valores que devuelve cada instancia deben ser inmutable Entonces, para la pregunta del OP, no creo que esto sea equivalente al enlace de tipo SQL 'PreparedStatement'. – javabrett

Cuestiones relacionadas