XPath: ограничить область действия набора результатов - PullRequest
3 голосов
/ 10 января 2011

Учитывая XML

<a>
    <c>
        <b id="1" value="noob"/>
    </c>
    <b id="2" value="tube"/>
    <a>
        <c>
            <b id="3" value="foo"/>
        </c>
        <b id="4" value="goo"/>
        <b id="5" value="noob"/>
        <a>
            <b id="6" value="near"/>
            <b id="7" value="bar"/>
        </a>
    </a>
</a>

и запрос Xpath 1.0

//b[@id=2]/ancestor::a[1]//b[@value="noob"]

Приведенный выше Xpath возвращает оба идентификатора узла 1 и 5. Цель состоит в том, чтобы ограничить результат только узломid = 1, поскольку это единственный @value="noob" элемент, который является потомком того же <a>, который (//b[@id=2]) также является потомком.

Другими словами, "Найти все b элементы со значением "noob", являющиеся потомками элемента a , который также имеет потомка с идентификатором 2, но не является потомком любого другого элемента a ».Как это для извилистых?На практике число и значения идентификатора будут переменными, и будут сотни типов узлов.

Если идентификатор = 2, мы ожидаем вернуть элемент id = 1, а не id = 5, поскольку он содержится в другом aэлемент.Если id = 4, мы ожидаем, что вернем id = 5, но не id = 1, так как он не является элементом первого предка как id = 4.

Редактировать: На основев комментариях Димитре и Алехандро я нашел эту полезную запись в блоге, объясняющую использование count () с |Союз оператора, а также некоторые другие отличные советы.

Ответы [ 3 ]

2 голосов
/ 11 января 2011

Во-первых, у этого

есть какой-то способ ограничить результирующий набор элементами <b>, которые ТОЛЬКО являются потомками непосредственного <a> элемента начального узла (//b[@id=2])?

//b[@value='noob'][ancestor::a[1]/b/@id=2]

Это не то же самое, что:

Начиная с узла, чей идентификатор равен 2, найдите все элементы со значением "noob"которые являются потомками непосредственного родительского элемента c, не проходя через другой элемент c

, который:

//c[b/@id=2]//*[.='noob'][ancestor::c[1][b/@id=2]]

Помимо этих выражений, когда вы имеете дело с "метками контекста"можно использовать тест членства в наборе, как в:

$node[count(.|$node-set)=count($node-set)]

Я оставляю вам его использование для этого случая в качестве упражнения ...

2 голосов
/ 11 января 2011

Использование :

//b[@value='noob']
      [count(ancestor::a[1] | //b[@id=2]/ancestor::a[1]) = 1]

Объяснение :

Второй предикат гарантирует, что оба элемента b имеют одинакового ближайшего предка a.

Помните : в XPath 1.0 тест для идентификации узла:

count($n1 | $n2) = 1
0 голосов
/ 11 января 2011

//b[@id=2]/ancestor::a[1]//b[@value="noob" and not(ancestor::a[2]=//b[@id=2]/ancestor::a[1])]? это работает только для вашего случая, но не уверен, насколько он должен быть универсальным!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...