XPath: Отримайте батьківський вузол з дочірнього вузла


157

Мені потрібно отримати батьківський вузол для дочірнього вузла title 50

На даний момент я лише використовую

//*[title="50"]

Як я міг отримати його батька? Результатом повинен бути storeвузол.


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

Відповіді:


295

Використовуйте parentосі з назвою батьківського вузла.

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

Цей XPath вибере батьківський вузол, лише якщо він є store .

Але ви також можете скористатися одним із них

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

Ці xpaths виберуть будь-який батьківський вузол. Тож якщо документ зміниться, ви завжди будете вибирати вузол, навіть якщо це не той вузол, який ви очікуєте.

EDIT

Що відбувається в наведеному прикладі, коли батько - це велосипед, але батько батьків - це магазин?

Це підйом?

Ні, він вибирає магазин лише у тому випадку, якщо він є батьківським вузлом, який відповідає //*[title="50"].

Якщо ні, чи існує метод підняття в таких випадках і повернення None, якщо такого немає?

Так, можна використовувати ancestorоси

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

Це дозволить вибрати всі предки відповідності вузлів, //*[title="50"]що є `магазинами. Напр

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

Результат вибору XPath


7
Ви можете також використовувати parent::*скорочений синтаксис ..(приклад: //*[title="50"]/..) або вкладений предикат (приклад: //*[*[title="50"]])
Daniel Хейлі

1
Додаткова інформація: w3.org/TR/xpath/#axes та w3.org/TR/xpath/#path-abbrev
Даніель Хейлі

3
Або parent::node()що відповідає ярлику ..і краще на мій погляд. Насправді parent::*обмежений основний тип вузла осі, що в більшості випадків не є проблемою.
Людович Куті

3
Якщо ви використовуєте спробуйте .xpath('..')абоxpath('parent::node()')
briankip

"Цей XPath вибере батьківський вузол лише у тому випадку, якщо це магазин." - і що відбувається в наведеному прикладі, де батьків є, bicycleале батько батьків є store? Це підйом? Якщо ні, то чи існує метод підняття в таких випадках і повернення, Noneякщо такого батька немає?
Мартін Тома

31

Як альтернативу ви можете використовувати ancestor.

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

Це потужніше, ніж parentтому, що його можуть дістати навіть бабуся і дідусь чи великий прабабуся


20
Він не "потужніший". Це просто різне. Таким чином, вибір осі залежить від випадку використання.
Людович Куті

11

Ви можете використовувати дві крапки в кінці виразу. Дивіться цей приклад:

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

2

Нова, вдосконалена відповідь на старе, часто задаване питання ...

Як я міг отримати його батька? Результатом повинен бути storeвузол.

Використовуйте предикат , а не parent::чи ancestor::осі

Більшість відповідей тут вибирають, titleа потім переходять до цільового батьківського або предка ( store) елемента. Більш простий, прямий підхід - це в першу чергу вибирати батьківський або предковий елемент, уникаючи необхідності переходити до осей parent::або ancestor:::

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

Якщо елементи, що втручаються, можуть відрізнятися за назвою:

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

Або від імені та глибини:

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

Це не відповідає на запитання. Автор не обов'язково знає прізвище батьків достроково.
Кенн Себеста

1
@KennSebesta: Я оновив відповідь, щоб вирішити вашу проблему. Будь-ласка, видаліть свій голос, якщо ваше заперечення було вирішено, або повідомте мені, чи відчуваєте ви, що щось не відповідає з відповіддю. Дякую.
kjhughes

0

Це працює в моєму випадку. Я сподіваюся, що ви можете витягти з цього сенс.

//div[text()='building1' and @class='wrap']/ancestor::tr/td/div/div[@class='x-grid-row-checker']
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.