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>
GibboK
źródło

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

René Link
źródło
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
1
Dodatkowe informacje: w3.org/TR/xpath/#axes i w3.org/TR/xpath/#path-abbrev
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

Aminah Nuraini
źródło
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"]/..
phduarte
źródło
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"]
kjhughes
źródło
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']
Shivam Bharadwaj
źródło