XPath: pobierz węzeł nadrzędny z węzła podrzędnego


157

Potrzebuję węzła nadrzędnego dla węzła podrzędnego title 50

W tej chwili używam tylko

//*[title="50"]

Jak mogę zdobyć jego rodzica? Wynik powinien być storewęzłem.


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

Odpowiedzi:


295

Użyj parentosi z nazwą węzła macierzystego.

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

Ta XPath wybierze węzeł nadrzędny tylko wtedy, gdy jest to plik store.

Ale możesz też użyć jednego z nich

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

Te ścieżki xpath wybiorą dowolny węzeł nadrzędny. Więc jeśli dokument się zmieni, zawsze będziesz wybierać węzeł, nawet jeśli nie jest to węzeł, którego oczekujesz.

EDYTOWAĆ

Co dzieje się w podanym przykładzie, gdzie rodzic jest rowerem, a rodzic rodzica sklepem?

Czy wznosi się?

Nie, wybiera sklep tylko wtedy, gdy jest rodzicem węzła, który pasuje //*[title="50"].

Jeśli nie, to czy istnieje metoda wejścia w takich przypadkach i zwrócenia None, jeśli nie ma takiego rodzica?

Tak, możesz używać ancestorosi

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

Spowoduje to wybranie wszystkich przodków pasującego węzła, //*[title="50"]czyli `sklepy. Na przykład

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

Wynik wyboru XPath


7
Można również użyć parent::*skróconej składni ..(np //*[title="50"]/..) lub zagnieżdżonego predykatu (na przykład: //*[*[title="50"]])
— Daniel Haley


3
Lub parent::node()który odpowiada skrótowi ..i jest moim zdaniem lepszy. W rzeczywistości parent::*ogranicza się do głównego typu węzła osi, co w większości przypadków nie stanowi problemu.
— Ludovic Kuty

3
Jeśli używasz try .xpath('..')orxpath('parent::node()')
— briankip,

„Ta ścieżka XPath wybierze węzeł nadrzędny tylko wtedy, gdy jest to sklep”. - a co dzieje się w podanym przykładzie, gdzie rodzic jest, bicyclea rodzic rodzica jest store? Czy wznosi się? Jeśli nie, to czy istnieje sposób na wejście w takich przypadkach i powrót, Nonejeśli nie ma takiego rodzica?
— Martin Thoma

31

Jako alternatywę możesz użyć ancestor.

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

Jest potężniejszy niż parentten, który może dostać nawet dziadek lub pradziadek


20
Nie jest „mocniejszy”. Jest po prostu inny. Zatem wybór osi zależy od przypadku użycia.
— Ludovic Kuty

11

Możesz również użyć dwóch kropek na końcu wyrażenia. Zobacz ten przykład:

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

2

Nowa, ulepszona odpowiedź na stare, często zadawane pytanie ...

Jak mogę zdobyć jego rodzica? Wynik powinien być storewęzłem.

Użyj predykatu zamiast osi parent::lubancestor::

Większość odpowiedzi tutaj wybiera, titlea następnie przechodzi do docelowego storeelementu nadrzędnego lub przodka ( ). Prostszym, bezpośrednim podejściem jest bezpośrednie wybranie elementu nadrzędnego lub nadrzędnego, eliminując potrzebę przechodzenia do osi a parent::lub ancestor:::

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

Jeżeli występujące elementy różnią się nazwą:

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

Lub, z nazwy i dogłębności:

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

To nie odpowiada na pytanie. Autor niekoniecznie zna imię rodzica z wyprzedzeniem.
— Kenn Sebesta

1
@KennSebesta: Zaktualizowałem odpowiedź, aby rozwiązać Twój problem. Usuń swój głos przeciw, jeśli Twój sprzeciw został uwzględniony, lub daj mi znać, jeśli uważasz, że odpowiedź jest nie tak. Dzięki.
— kjhughes

0

To działa w moim przypadku. Mam nadzieję, że potrafisz wydobyć z tego znaczenie.

//div[text()='building1' and @class='wrap']/ancestor::tr/td/div/div[@class='x-grid-row-checker']
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.