#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 для таких узлов..