).

этомОтвет переполнения стека представьте, что вам нужно выбрать конкретную таблицу, а затем все ее строки. Из-за вседозволенности 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, которое разрешает дополнительный элемент в иерархии селектора?

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

 Phrogz06 янв. 2011 г., 04:30
Ох, и ради простоты и общности я игнорируюthead а такжеtfoot элементы легальные в HTML.

Ответы на вопрос(3)

Решение Вопроса

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

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

Если вы хотите одно выражение без объединения наборов узлов:

//tr[(.|parent::tbody)[1]/parent::table[@id='foo']]
 Dimitre Novatchev06 янв. 2011 г., 18:04
@Phrogz: Это выражение содержит обратные оси и менее эффективно, чем выражение, содержащее только прямые оси. Что касается "СУХОГО" состояния, вы также можете рассмотреть понятность выражения, которое, безусловно, связано с его сохранностью. :)
 Phrogz06 янв. 2011 г., 18:13
@Dimitre Спасибо за ваш комментарий по эффективности. Вы правы в том, что простое чередование (ваш ответ и первое выражение в этом ответе) легче понять, даже если оно немного более подвержено ошибкам редактирования и сложнее в обслуживании.
 Dimitre Novatchev06 янв. 2011 г., 20:49
@Phrogz: легче понять, значит легче поддерживать!
 user35781206 янв. 2011 г., 21:19
@Phrogz: Я также думаю, что выражение объединения более простое и читаемое. Но, если у вас нет очень умного движка XPath, я думаю, что выражение объединения (с двумяdescendant ось) будет менее эффективной
 Phrogz06 янв. 2011 г., 17:24
Ваш первый ответ - то, что предлагал Димитр. Однако я изменил принятие вашего второго выражения, так как оно более СУХОЕ.

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

   foo"]/*[self::tbody or self::thead or self::tfoot]/tr
   |
   ;foo"]/tr

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

 Dimitre Novatchev30 янв. 2013 г., 14:01
@ StevenD.Majewski,//table[@id="foo"]/(tr|(tbody|thead|tfoot)/tr)
 Steven D. Majewski29 янв. 2013 г., 21:43
Что является более элегантной версией XPath 2.0? Лучшее, что я мог понять, это чередование шагов "." и необязательная часть. С Saxon на TEI это сработало для меня: /TEI.2/text/(.|group/text)/body/div1
 Dimitre Novatchev06 янв. 2011 г., 06:38
@Phrogz: Нет, это почти так же просто, как мое первоначальное выражение - см. Редактирование. Это может быть намного более элегантно с XPath 2.0 и даже намного более элегантно с документом XML с известной схемой XML (как в случае с XHTML).
 Phrogz06 янв. 2011 г., 04:56
Я ценю ваш опыт в этой области, но действительно ли это лучшее, что можно сделать? Если первая и последняя части xpath просто «таблица» и «tr», это не так уж плохо, но с чем-то вродеdiv[@id="contents]//table[@class="comments"](/tbody)?/tr/[td//text()[contains(., 'targetString')]] это становится оченьDRY дублировать выражение вокруг одного варианта.

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

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

XPathTester.com демо

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

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

//table[@id="foo"]/(thead|tbody|tfoot|.)/tr
 Palec02 сент. 2016 г., 20:59
Я не уверен, почему это не работает в XPath 1.0, хотя. Похоже, так и должно быть, потому что(tbody|.) выглядит как действительныйFilterExpr знак (PrimaryExpr'(' Expr ')'OrExprAndExprEqualityExprRelationalExprAdditiveExprMultiplicativeExprUnaryExprUnionExpr).

Ваш ответ на вопрос