XPath для поиска ближайшего элемента предка, который содержит элемент с атрибутом с определенным значением

ancestor::foo[bar[@attr="val"]]

Я думал, что это сработает, но это не так. Мне нужно найти ближайший элемент foo, который растет в дереве с дочерним элементом bar, который, в свою очередь, имеет атрибут attr val.

Ответы

Ответ 1

Это должно работать:

//*[ancestor::foo[bar[@attr="val"]]]

или, альтернативно,

root/foo/bar[ancestor::foo[bar[@attr="val"]]]

соответствует второму элементу <bar>

<root>
    <foo>
        <bar attr="xxx"></bar>
    </foo>
    <foo>
        <bar attr="val"></bar>
    </foo>
    <foo>
        <bar attr="zzz"></bar>
    </foo>
</root>

Ответ 2

Обновлено для отражения решения, предназначенного OP.

См. ответ @David

Для примера xml ниже,

<root>
<foo id="0">
    <bar attr="val"/>
    <foo id="1">
        <bar attr="xxx"/>
    </foo>
    <foo id="2">
        <bar attr="val">
            <one>1</one>
            <two>
                <three>3</three>
            </two>
        </bar>
    </foo>
</foo>

действительный xpath на обратной оси с < три > как контекст node, допустимым решением является

./ancestor::foo[bar[@attr='val']][position() = 1]

"./" не является обязательным. position() = 1 не является необязательным, так как в противном случае также будет возвращен предок foo, удовлетворяющий предикатам.

Старый ответ: игнорировать

Это старый вопрос. но кто-нибудь заинтересован, следующее должно получить вас, что первоначальный вопрос.

Обратная ось

//bar[@attr='val']/ancestor::*[position()=1]

Передняя ось

//*[child::bar[@attr='val']]

Ответ 3

По моему мнению, лучший ответ был предоставлен человеком, который задал вопрос. Его решение должно было вернуть всех предков. Он хочет только ближайший, который находится с позицией() = 1, поэтому его выражение xpath должно быть слегка изменено на:

ancestor::foo[bar[@attr="val"] and position() = 1]

Если он пишет, что ancestor::foo[bar[@attr="val"]] ничего не вернул, у него была другая проблема в его xml или в его предположении о текущем элементе его контекста оценки XPath.

Другие ответы (начиная с // ) на самом деле не отвечают на вопрос и даже если они случайно встретили потребность кого-то, поэтому они неэффективны: они выбирают ВСЕ элементы в XML файле, применяя к ним фильтр потом. Хотя то, что относительный xpath, предложенный мной или человеком, который задавал этот вопрос, просто будет искать через несколько элементов, начиная с текущего node до родителя и его родителя и т.д. - он будет очень эффективным даже с большим XML файлы.