Подтвердить что ты не робот

XPath с дополнительным элементом в иерархии

Как и в этом ответе, представьте, что вам нужно выбрать определенную таблицу, а затем все ее строки. Из-за вседозволенности HTML все три из следующих являются юридической разметкой:

<table id="foo"><tr>...</tr></table>
<table id="foo"><tbody><tr>...</tr></tbody></table>
<table id="foo"><tr>...</tr><tbody><tr>...</tr></tbody></table>

Вы беспокоитесь о таблицах, вложенных в таблицы, и поэтому не хотите использовать XPath, как, например, table[@id="foo"]//tr.

Если вы можете указать желаемый XPath в качестве регулярного выражения, он может выглядеть примерно так: table[@id="foo"](/tbody)?/tr

В общем, как вы можете указать выражение XPath, которое допускает необязательный элемент в иерархии селектора?

Чтобы быть ясным, я не пытаюсь решить проблему реального мира или выбрать конкретный элемент конкретного документа. Я прошу о методах решения класса проблем.

4b9b3361

Ответ 1

Я не понимаю, почему вы не можете использовать это:

//table[@id='foo']/tr|//table[@id='foo']/tbody/tr

Если вам нужно одно выражение без node set union:

//tr[(.|parent::tbody)[1]/parent::table[@id='foo']]

Ответ 2

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

   //table[@id="foo"]/*[self::tbody or self::thead or self::tfoot]/tr
   |
   //table[@id="foo"]/tr

Выберите любой элемент tr, который является дочерним элементом любого table, который имеет атрибут id "foo" или любой элемент tr, который является дочерним элементом tbody, являющимся дочерним элементом any table.

Ответ 3

В XPath 2.0 необязательный шаг может быть выражен как (tbody|.).

//table[@id="foo"]/(tbody|.)/tr

XPathTester.com demo

Труба (|) обозначает union (из двух node -sets), точка (.) обозначает шаг идентичности (возвращающий только то, что сделал предыдущий шаг).

Это можно расширить, включив в него более дополнительные элементы:

//table[@id="foo"]/(thead|tbody|tfoot|.)/tr