Различные * стратегии выбора в XPath

#xml #xpath

#xml #xpath

Вопрос:

В чем различия между следующими подходами к целевым конечным узлам документа на основе некоторых критериев?

 <!-- using //* -->
//*[contains(@class, "w4")]       

<!-- using //node() -->
//node()[contains(@class, "w4")]

<!-- using //. -->
//.[contains(@class, "w4")]
 

Все три из них «работают», чтобы выбрать один и тот же узел в некотором примере xml, поэтому мне было интересно, есть ли между ними какая-либо разница, и если они все одинаковые, что предпочтительнее (также, почему я не могу просто использовать //[contains(@class, "w4")] с пустым узлом, не // подразумевает ничего из корневой узел?).

Ответ №1:

//* выделяет все элементы в документе.

//node() также выбирает другие типы узлов (комментарии, текстовые узлы и т.д.), Но только элементы будут соответствовать предикату, который ищет атрибуты, поэтому в конечном итоге он будет эквивалентен.

//. это очень однообразно, вероятно, потому, что оно работает только в XPath 2.0 и не делает ничего, что вы не могли бы сделать каким-либо другим способом. Я должен был подумать о том, что именно это значит. Он расширяется до /descendant-or-self::node()/. , что эквивалентно пропуску /. в конце, что означает, что единственное отличие от //node() заключается в том, что он также выбирает корневой узел документа. Но опять же, у этого не будет никаких атрибутов, поэтому он не пройдет мимо предиката, который проверяет @class .

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

Удивительно, как часто люди пытаются //[predicate] это сделать , но это совершенно неграмотно. // само по себе это все равно, что сказать «выберите», не сказав, что вы хотите выбрать; это незаконченное предложение. И если вы еще не сказали, что вы хотите выбрать, нет смысла затем выбирать его подмножество.

Комментарии:

1. спасибо за этот ответ. Один вопрос, касающийся //node() — только элементы будут соответствовать предикату, который ищет атрибуты, поэтому он в конечном итоге эквивалентен. Не могли бы вы подробнее остановиться на этом?

2. //node() может выбирать текстовые узлы или комментарии, но текстовые узлы и комментарии не имеют атрибутов, поэтому предикат, который ищет атрибуты like [@class = 'abc'] , всегда будет false для таких узлов..