XPath: obtenir le nœud parent du nœud enfant


157

J'ai besoin d'obtenir le nœud parent du nœud enfant title 50

Pour le moment, je n'utilise que

//*[title="50"]

Comment pourrais-je avoir son parent? Le résultat doit être le storenœud.


<?xml version="1.0" encoding="utf-8"?>
<d:data xmlns:d="defiant-namespace" d:mi="23">
    <store d:mi="22">
        <book price="12.99" d:price="Number" d:mi="4">
            <title d:constr="String" d:mi="1">Sword of Honour</title>
            <category d:constr="String" d:mi="2">fiction</category>
            <author d:constr="String" d:mi="3">Evelyn Waugh</author>
        </book>
        <book price="8.99" d:price="Number" d:mi="9">
            <title d:constr="String" d:mi="5">Moby Dick</title>
            <category d:constr="String" d:mi="6">fiction</category>
            <author d:constr="String" d:mi="7">Herman Melville</author>
            <isbn d:constr="String" d:mi="8">0-553-21311-3</isbn>
        </book>
        <book price="8.95" d:price="Number" d:mi="13">
            <title d:constr="String" d:mi="10">50</title>
            <category d:constr="String" d:mi="11">reference</category>
            <author d:constr="String" d:mi="12">Nigel Rees</author>
        </book>
        <book price="22.99" d:price="Number" d:mi="18">
            <title d:constr="String" d:mi="14">The Lord of the Rings</title>
            <category d:constr="String" d:mi="15">fiction</category>
            <author d:constr="String" d:mi="16">J. R. R. Tolkien</author>
            <isbn d:constr="String" d:mi="17">0-395-19395-8</isbn>
        </book>
        <bicycle price="19.95" d:price="Number" d:mi="21">
            <brand d:constr="String" d:mi="19">Cannondale</brand>
            <color d:constr="String" d:mi="20">red</color>
        </bicycle>
    </store>
</d:data>

Réponses:


297

Utilisez les parentaxes portant le nom du nœud parent.

//*[title="50"]/parent::store

Ce XPath ne sélectionnera le nœud parent que s'il s'agit d'un store.

Mais vous pouvez également utiliser l'un de ces

//*[title="50"]/parent::*
//*[title="50"]/..

Ces xpaths sélectionneront n'importe quel nœud parent. Donc, si le document change, vous sélectionnerez toujours un nœud, même si ce n'est pas le nœud que vous attendez.

ÉDITER

Que se passe-t-il dans l'exemple donné où le parent est un vélo mais le parent du parent est un magasin?

Est-ce qu'il monte?

Non, il ne sélectionne le magasin que s'il s'agit d'un parent du nœud correspondant //*[title="50"].

Si non, existe-t-il une méthode pour remonter dans de tels cas et renvoyer None s'il n'y a pas de tel parent?

Oui, vous pouvez utiliser des ancestoraxes

//*[title="50"]/ancestor::store

Cela sélectionnera tous les ancêtres du nœud correspondant //*[title="50"]qui sont `stores. Par exemple

<data xmlns:d="defiant-namespace" d:mi="23">
    <store mi="1">
        <store mi="22">
            <book price="8.95" d:price="Number" d:mi="13">
                <title d:constr="String" d:mi="10">50</title>
                <category d:constr="String" d:mi="11">reference</category>
                <author d:constr="String" d:mi="12">Nigel Rees</author>
            </book>
        </store>
    </store>
</data>

Résultat de la sélection XPath


7
Vous pouvez également utiliser la parent::*syntaxe abrégée ..(exemple: //*[title="50"]/..) ou un prédicat imbriqué (exemple: //*[*[title="50"]])
Daniel Haley

1

3
Ou parent::node()qui correspond au raccourci ..et qui est mieux à mon avis. En fait, parent::*se limite au type de nœud principal de l'axe ce qui dans la plupart des cas ne pose pas de problème.
Ludovic Kuty

3
Si vous utilisez try .xpath('..')orxpath('parent::node()')
briankip

"Ce XPath ne sélectionnera le nœud parent que s'il s'agit d'un magasin." - et que se passe-t-il dans l'exemple donné où le parent est bicyclemais que le parent du parent est store? Est-ce qu'il monte? Sinon, y a-t-il une méthode pour remonter dans de tels cas et revenir en l' Noneabsence d'un tel parent?
Martin Thoma

31

Juste comme alternative, vous pouvez utiliser ancestor.

//*[title="50"]/ancestor::store

C'est plus puissant que parentcar il peut même obtenir le grand-parent ou l'arrière-arrière-grand-parent


20
Ce n'est pas "plus puissant". C'est juste différent. Ainsi le choix de l'axe dépend du cas d'utilisation.
Ludovic Kuty

11

Vous pouvez également utiliser les deux points à la fin de l'expression. Voir cet exemple:

//*[title="50"]/..

2

Nouvelle réponse améliorée à une ancienne question fréquemment posée ...

Comment pourrais-je avoir son parent? Le résultat doit être le storenœud.

Utilisez un prédicat plutôt que l' axe parent::ouancestor::

La plupart des réponses ici sélectionnent le title, puis remontent jusqu'à l' storeélément parent ou ancestor ( ) ciblé . Une approche plus simple et directe consiste à sélectionner l'élément parent ou ancêtre directement en premier lieu, évitant ainsi d'avoir à parcourir les axes a parent::ou ancestor:::

//*[book/title = "50"]

Si le nom des éléments intermédiaires varie:

//*[*/title = "50"]

Ou, en nom et en profondeur:

//*[.//title = "50"]

Cela ne répond pas à la question. L'auteur ne connaît pas nécessairement le nom du parent à l'avance.
Kenn Sebesta le

1
@KennSebesta: J'ai mis à jour la réponse pour répondre à votre préoccupation. Veuillez supprimer votre vote négatif si votre objection a été traitée, ou faites-moi savoir si vous pensez que quelque chose ne va pas avec la réponse. Merci.
kjhughes le

0

Cela fonctionne dans mon cas. J'espère que vous pourrez en tirer un sens.

//div[text()='building1' and @class='wrap']/ancestor::tr/td/div/div[@class='x-grid-row-checker']
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.