XPath: ottiene il nodo padre dal nodo figlio


157

Ho bisogno di ottenere il nodo padre per il nodo figlio title 50

Al momento sto usando solo

//*[title="50"]

Come potrei ottenere il suo genitore? Il risultato dovrebbe essere il storenodo.


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

Risposte:


297

Utilizzare gli parentassi con il nome del nodo padre.

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

Questo XPath selezionerà il nodo genitore solo se è a store.

Ma puoi anche usare uno di questi

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

Questi xpath selezioneranno qualsiasi nodo genitore. Quindi, se il documento cambia, selezionerai sempre un nodo, anche se non è il nodo che ti aspetti.

MODIFICARE

Cosa succede nell'esempio dato in cui il genitore è una bicicletta ma il genitore del genitore è un negozio?

Sale?

No, seleziona il negozio solo se è un genitore del nodo corrispondente //*[title="50"].

In caso contrario, esiste un metodo per salire in questi casi e restituire None se non esiste un genitore del genere?

Sì, puoi usare gli ancestorassi

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

Questo selezionerà tutti gli antenati della corrispondenza dei nodi //*[title="50"]che sono `store. Per esempio

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

Risultato della selezione XPath


7
Si potrebbe anche utilizzare la parent::*sintassi abbreviata ..(ad esempio: //*[title="50"]/..) o di un predicato annidato (ad esempio: //*[*[title="50"]])
Daniel Haley


3
O parent::node()che corrisponde alla scorciatoia ..ed è meglio secondo me. In effetti parent::*è limitato al tipo di nodo principale dell'asse che nella maggior parte dei casi non costituisce un problema.
Ludovic Kuty,

3
Se stai usando try .xpath('..')oxpath('parent::node()')
briankip

"Questo XPath selezionerà il nodo genitore solo se è un negozio." - e cosa succede nell'esempio dato in cui il genitore si trova bicyclema è il genitore del genitore store? Sale? In caso contrario, esiste un metodo per salire in questi casi e tornare Nonese non esiste un genitore del genere?
Martin Thoma,

31

Proprio come alternativa, puoi usare ancestor.

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

È più potente di parentquando può ottenere anche il nonno o il bisnonno


20
Non è "più potente". È solo diverso. Pertanto, la scelta dell'asse dipende dal caso d'uso.
Ludovic Kuty,

11

Puoi anche usare i due punti alla fine dell'espressione. Vedi questo esempio:

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

2

Nuova risposta migliorata a una vecchia domanda frequente ...

Come potrei ottenere il suo genitore? Il risultato dovrebbe essere il storenodo.

Utilizzare un predicato anziché l' asse parent::oancestor::

La maggior parte delle risposte qui seleziona titlee quindi attraversa l' storeelemento genitore o antenato ( ) targetizzato . Un approccio più semplice e diretto consiste nel selezionare l'elemento genitore o antenato direttamente in primo luogo, ovviando alla necessità di attraversare a parent::o ancestor::assi:

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

Se gli elementi intermedi dovessero variare nel nome:

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

Oppure, nel nome e nella profondità:

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

Questo non risponde alla domanda. L'autore non conosce necessariamente in anticipo il nome del genitore.
Kenn Sebesta,

1
@KennSebesta: ho aggiornato la risposta per rispondere alla tua preoccupazione. Rimuovi il tuo voto negativo se la tua obiezione è stata affrontata o fammi sapere se ritieni che qualcosa non funzioni nella risposta. Grazie.
kjhughes,

0

Questo funziona nel mio caso. Spero che tu possa estrarne il significato.

//div[text()='building1' and @class='wrap']/ancestor::tr/td/div/div[@class='x-grid-row-checker']
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.