expresiones - xpath expression java
EjecuciĆ³n de XPath en el nodo hijo (4)
Intento hacer una búsqueda xpath en los nodos devueltos por la búsqueda de xpath, pero no parece funcionar como esperaba. Las XPaths ejecutadas en los nodos secundarios de un documento parecen ejecutarse contra el nodo raíz del documento (en el ejemplo, la etiqueta de inventario.), en lugar de la raíz del nodo proporcionado.
¿Me estoy perdiendo de algo? Soy nuevo en XPath.
Además, no responda "just do // book [author = ''Neal Stephenson'' / title". Tengo un caso de uso legítimo, y este es un ejemplo simplificado.
Fragmento de código
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true);
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse("src/main/java/books.xml");
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
Node book = (Node) xpath.evaluate("//book[author=''Neal Stephenson'']", doc, XPathConstants.NODE);
Node title = (Node) xpath.evaluate("/title", book, XPathConstants.NODE); // I get null here.
Node inventory = (Node) xpath.evaluate("/inventory", book, XPathConstants.NODE); // this returns a node.
book.xml
<inventory>
<book year="2000">
<title>Snow Crash</title>
<author>Neal Stephenson</author>
<publisher>Spectra</publisher>
<isbn>0553380958</isbn>
<price>14.95</price>
</book>
<book year="2005">
<title>Burning Tower</title>
<author>Larry Niven</author>
<author>Jerry Pournelle</author>
<publisher>Pocket</publisher>
<isbn>0743416910</isbn>
<price>5.99</price>
</book>
<book year="1995">
<title>Zodiac</title>
<author>Neal Stephenson</author>
<publisher>Spectra</publisher>
<isbn>0553573862</isbn>
<price>7.50</price>
</book>
<!-- more books... -->
</inventory>
Lo que es realmente extraño en la implementación de Java es que un Nodo extraído de un Documento aún hace referencia al Documento padre (vea Node.getOwnerDocument()
) y xpath lo usa para encontrar la raíz.
Otros han mencionado una forma de modificar el xpath para que realmente no comience desde la raíz eliminando las barras.
Tenía un problema similar, pero quería que xpath manejara tanto los documentos raíz como los nodos secundarios (con un xpath como /title
). La solución fue clonar el nodo: Node.cloneNode(true)
. Tenga en cuenta el parámetro true
que hace que el nodo agite su documento principal.
... Al final, duele mucho el rendimiento y es preferible tener xpaths separados para manejar el nodo y el documento.
Solo tome el corte inicial de sus subconsultas y debería estar bien. Así que obtienes tus libros a través de "//book"
, y desde allí solo tienes "title"
, "inventory"
etc. para obtener los bits del niño.
en Xpath, "." (Punto) representa el documento actual. Por lo tanto, escriba su cadena XPATH después de un "." (Punto).
ex:
"./title"
o
".//title"
Lo que quieras....
eliminar la barra solo funciona si es hijo del nodo. ¿Qué sucede si desea utilizar la funcionalidad // (en el documento actual)?
Entonces, usa el punto (.)
Muchas gracias por las respuestas anteriores también :).
/foo
seleccionará basado en el nodo raíz, ignorando el contexto en el que está evaluando el xpath. foo
(sin la barra) es lo que quieres; que selecciona basado en el nodo actual.
https://www.w3schools.com/xml/xpath_syntax.asp da un poco más de información.