web-dev-qa-db-fra.com

Exécution de XPath sur le nœud enfant

J'essaie de faire une recherche xpath sur les nœuds retournés par la recherche xpath, mais cela ne semble pas fonctionner comme je m'y attendais.Les XPaths exécutés sur les nœuds enfants d'un document semblent être exécutés contre le nœud racine du document (dans l'exemple, la balise d'inventaire.), au lieu de la racine du nœud fourni.

Est-ce que j'ai râté quelque chose? Je suis nouveau sur XPath.

Aussi, ne répondez pas "faites juste // book [author = 'Neal Stephenson'/title". J'ai un cas d'utilisation légitime, et ceci est un exemple simplifié.

Extrait de code

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>
49
Jeeyoung Kim

/foo sélectionnera en fonction du nœud racine, en ignorant le contexte par rapport auquel vous évaluez le xpath. foo (sans la barre oblique) est ce que vous voulez; qui sélectionne en fonction du nœud actuel.

https://www.w3schools.com/xml/xpath_syntax.asp donne un peu plus d'informations.

49
Pete Hodgson

dans Xpath, "." (Le point) représente le document actuel. Donc, écrivez votre chaîne XPATH après un "." (Point).

ex:

"./title"

ou

".//title"

Tout ce que vous voulez....

la suppression de la barre oblique ne fonctionne que s'il s'agit d'un enfant du nœud. Que faire si vous souhaitez utiliser la fonctionnalité // (n'importe où dans le document actuel)?

Donc, utilisez le point (.)

Merci beaucoup pour les réponses ci-dessus aussi :).

25
Salman

Supprimez simplement la barre oblique de vos sous-requêtes et tout ira bien. Vous obtenez donc vos livres via "//book", et à partir de là, c'est juste "title", "inventory" etc pour obtenir les bits enfants.

7
Corey Porter

Ce qui est vraiment bizarre dans l'implémentation Java est qu'un Node extrait d'un document fait toujours référence au document parent (voir Node.getOwnerDocument()) et xpath l'utilise pour trouver la racine.

D'autres ont mentionné un moyen de modifier le xpath pour réellement pas démarrer à partir de la racine en supprimant les barres obliques.

J'ai eu un problème similaire mais je voulais que xpath gère à la fois les documents racine et les nœuds enfants (avec un xpath comme /title). La solution consistait à cloner le nœud: Node.cloneNode(true). Notez le paramètre true qui fait en sorte que le Node secoue son document parent).

... En fin de compte, cela nuit trop aux performances et avoir des xpath séparés pour gérer Node et Document a été préféré.

4
mauhiz