kzen.dev
  • Вопросы
  • Метки
  • Пользователи
Оповещения
Вознаграждения
Регистрация
После регистрации, сможете получать уведомления об ответах и комментариях на Ваши вопросы.
Вход
Если у Вас уже есть аккаунт, войдите чтобы проверить новые уведомления.
Тут будут вознаграждения за добавленные вопросы, ответы и комментарий.
Дополнительно
Источник
Редактировать
 Maksee
Maksee
Вопрос

Работает ли двойной слэш в предикате XPath так же, как и в самом пути

Я играл с различными XPath-запросами с помощью XPather (работает только в старых версиях firefox) и заметил разницу между результатами следующих запросов

Этот показывает некоторые результаты

//div[descendant::table/descendant::td[4]] 

Здесь показан пустой список

//div[//table//td[4]]

Они отличаются из-за каких-то правил или это просто неправильное поведение конкретной реализации интерпретатора XPath? (Кажется, что XPather используется из движка FF, это просто отличный простой GUI для запросов).

7 2012-04-07T11:06:39+00:00 2
Программирование
xpath
Решение / Ответ
Martin Honnen
Martin Honnen
7-го апреля 2012 в 11:15
2012-04-07T11:15:48+00:00
Дополнительно
Источник
Редактировать
#15880936

В XPath 1.0 // является сокращением для /descendant-or-self::node()/, поэтому ваш первый путь будет /descendant-or-self::node()/div[descendant::table/descendant::td[4]], в то время как второй путь будет совсем другим /descendant-or-self::node()/div[/descendant-or-self::node()/table/descendant-or-self::node()/td[4]]. Основная разница заключается в том, что в первом предикате вы ищете потомков относительно элемента div, а во втором предикате вы ищете потомков от корневого узла / (также называемого узлом документа). Вам может понадобиться //div[.//table//td[4]], чтобы второе выражение пути было ближе к первому.

[edit]. Вот пример:

<html>
  <body>
    <div>
      <table>
        <tbody>
          <tr>
            <td>1</td>
          </tr>
          <tr>
            <td>2</td>
          </tr>
          <tr>
            <td>3</td>
          </tr>
          <tr>
            <td>4</td>
          </tr>
        </tbody>
      </table>
    </div>
  </body>
</html>

В этом примере путь //div[descendant::table/descendant::td[4]] выбирает элемент div, поскольку у него есть дочерний table, у которого есть четвертый потомок td.

Однако с //div[.//table//td[4]] мы ищем //div[./descendant-or-self::node()/table/descendant-or-self::node()/td[4]], который является сокращением для //div[./descendant-or-self::node()/table/descendant-or-self::node()/child::td[4]] и нет элемента, имеющего четвертый td дочерний элемент.

Надеюсь, это объясняет разницу, если вы используете //div[.//table/descendant::td[4]], то вы должны получить тот же результат, что и с вашей оригинальной формой.

Martin Honnen
Martin Honnen
Редактировал ответ 7-го апреля 2012 в 12:42
9
0
 CiaPan
CiaPan
28-го февраля 2014 в 11:45
2014-02-28T23:45:43+00:00
Дополнительно
Источник
Редактировать
#15880937

В документе W3C по XPath есть важное замечание:

XML Path Language (XPath) Version 1.0     2 Location Paths           2.5 Сокращенный синтаксис

NOTE: Путь расположения //para[1] означает не то же самое, что путь расположения /descendant::para[1]. Последний выбирает первый элемент-потомок para; первый выбирает все элементы-потомки para, которые являются первыми дочерними элементами para своих родителей.

Это означает, что двойная косая черта внутри пути является не только сокращением для /descendant-or-self::node()/, но и отправной точкой для следующего уровня итерации XML-дерева, что подразумевает, что выражение шага справа от // повторно выполняется на каждом потомке текущего контекстного узла.

Таким образом, точное значение предиката в этом пути

//div[ descendant::table/descendant::td[4] ]

это:

  • построить последовательность всех узлов <table>, нисходящих к текущему <div>,
  • для каждой такой <table> построить последовательность всех элементов-потомков <td> и объединить их в одну последовательность,
  • отфильтруйте эту последовательность для четвертого элемента.

Наконец, путь возвращает все элементы <div> в документе, которые имеют по крайней мере четыре ячейки данных во всех своих вложенных таблицах. А поскольку в документе есть таблицы, которые имеют 4 ячейки или более (включая ячейки во вложенных таблицах, конечно), все выражение выбирает их соответствующих <div> предков.

С другой стороны, предикат в

//div[ //table//td[4] ]

означает:

  • просканировать все дерево документов на наличие элементов <table> (точнее, проверить корневой узел и каждого потомка корня, если у него есть дочерний элемент <table>),
  • для каждой найденной таблицы проверить ее поддерево на наличие элементов, имеющих четвертый <td>подэлемент (т.е. проверить, имеет ли таблица или любой из ее потомков как минимум четыре <td>детища).

Обратите внимание, что подвыражение предиката не зависит от узла контекста. Это глобальный путь, разрешающийся в некоторую последовательность узлов (возможно, пустую), поэтому булево значение предиката зависит только от структуры документа. Если оно истинно, то весь путь возвращает последовательность всех элементов <div> в документе, иначе - пустую последовательность.

Наконец, предикат будет true, если в любой таблице есть элемент, имеющий 4 (как минимум) ячейки данных.
Насколько я могу судить, все строки <tr> содержат две или три ячейки - нет элемента с 4 или более дочерними <td>, поэтому подвыражение предиката возвращает пустую последовательность, предикат false и весь путь отфильтровывается. Результат: ничего (пустая последовательность).

 CiaPan
CiaPan
Редактировал ответ 30-го марта 2016 в 10:39
4
0
Добавить вопрос
Категории
Все
Технологий
Культура / Отдых
Жизнь / Искусство
Наука
Профессии
Бизнес
Пользователи
Все
Новые
Популярные
1
Ilya Smirnov
Зарегистрирован 5 дней назад
2
Денис Васьков
Зарегистрирован 1 неделю назад
3
Dima Patrushev
Зарегистрирован 1 неделю назад
4
sirojidddin otaboyev
Зарегистрирован 2 недели назад
5
Елена Гайдамамакинат
Зарегистрирован 2 недели назад
RU
© kzen.dev 2023
Источник
stackoverflow.com
под лицензией cc by-sa 3.0 с атрибуцией