XPath: Obter nó pai do nó filho

157

Preciso obter o nó pai para o nó filho title 50

No momento estou usando apenas

//*[title="50"]

Como eu consegui o pai? O resultado deve ser o storenó.


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

Respostas:

297

Use os parenteixos com o nome do nó pai.

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

Esse XPath selecionará apenas o nó pai se for um store.

Mas você também pode usar um desses

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

Esses xpaths selecionam qualquer nó pai. Portanto, se o documento for alterado, você sempre selecionará um nó, mesmo que não seja o nó esperado.

EDITAR

O que acontece no exemplo em que o pai é uma bicicleta, mas o pai é uma loja?

Subida?

Não, ele seleciona apenas o armazenamento se for um pai do nó que corresponde //*[title="50"].

Caso contrário, existe um método para subir nesses casos e retornar None se não houver tal pai?

Sim, você pode usar ancestoreixos

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

Isso selecionará todos os ancestrais do nó correspondente //*[title="50"]que são `lojas. Por exemplo

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

Resultado da seleção XPath

René Link
fonte
7
Você também pode usar a parent::*sintaxe abreviada ..(exemplo: //*[title="50"]/..) ou um predicado aninhado (exemplo: //*[*[title="50"]])
Daniel Haley
1
Informações adicionais: w3.org/TR/xpath/#axes e w3.org/TR/xpath/#path-abbrev
Daniel Haley
3
Ou o parent::node()que corresponde ao atalho ..e é melhor na minha opinião. De fato, parent::*é limitado ao tipo de nó principal do eixo, que na maioria dos casos não é um problema.
Ludovic Kuty
3
Se você estiver usando try .xpath('..')ouxpath('parent::node()')
briankip
"Este XPath selecionará apenas o nó pai se for uma loja." - e o que acontece no exemplo em que o pai está, bicyclemas o pai está store? Subida? Caso contrário, existe um método para subir em tais casos e retornar Nonese não houver tal pai?
Martin Thoma
31

Apenas como uma alternativa, você pode usar ancestor.

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

É mais poderoso do que parentjá que pode receber até avós ou bisavós

Aminah Nuraini
fonte
20
Não é "mais poderoso". É apenas diferente. Portanto, a escolha do eixo depende do caso de uso.
Ludovic Kuty
11

Você também pode usar os dois pontos no final da expressão. Veja este exemplo:

//*[title="50"]/..
phduarte
fonte
2

Resposta nova e aprimorada para uma antiga pergunta freqüente ...

Como eu consegui o pai? O resultado deve ser o storenó.

Use um predicado em vez do eixo parent::ouancestor::

A maioria das respostas aqui seleciona o elemento titlee, em seguida, percorre o elemento pai ou ancestral ( store). Uma abordagem mais simples e direta é selecionar o elemento pai ou ancestral diretamente em primeiro lugar, evitando a necessidade de passar para um parent::ou ancestor::eixos:

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

Os elementos intervenientes devem variar em nome:

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

Ou, em nome e profundidade:

//*[.//title = "50"]
kjhughes
fonte
Isso não responde à pergunta. O autor não sabe necessariamente o nome do pai antes do tempo.
Kenn Sebesta
1
@ KennSebesta: Atualizei a resposta para resolver sua preocupação. Remova o voto negativo se a sua objeção tiver sido resolvida ou entre em contato se achar que algo permanece errado com a resposta. Obrigado.
kjhughes 15/02
0

Isso funciona no meu caso. Espero que você possa extrair significado disso.

//div[text()='building1' and @class='wrap']/ancestor::tr/td/div/div[@class='x-grid-row-checker']
Shivam Bharadwaj
fonte