Получение текста с XPath, когда он похоронен в другом теге, например

Следующий XPath обычно достаточен для сопоставления всех якорей, текст которых содержит определенную строку:

//a[contains(text(), 'SENIOR ASSOCIATES')] 

Учитывая такой случай:

  SENIOR ASSOCIATES 

Текст завернут в , также есть и до того, как якорь закроется, и поэтому выше XPath ничего не возвращает.

Как можно адаптировать XPath так, чтобы он позволял содержать дополнительные tags, такие как , , , и т. Д., Все еще работая в стандартном случае?

Не используйте text() .

 //a[contains(., 'SENIOR ASSOCIATES')] 

Вопреки тому, что вы думаете, text() не дает вам текст элемента.

Это тест узла, т. Е. Выражение, которое выбирает список фактических узлов (!), А именно текстовых узлов дочерних элементов элемента.

Вот:

  SENIOR ASSOCIATES 

нет дочерних узлов текстового узла. Все текстовые узлы являются strong детьми. Таким образом, text() дает вам нулевые узлы.

Вот:

   SENIOR ASSOCIATES 

существует один дочерний a текстового узла. Он пуст (как в «только пробеле»).


. с другой стороны, выбирает только один узел (узел контекста, сам ).

Теперь, contains() ожидает строки как свои аргументы. Если один аргумент не является строкой, сначала выполняется преобразование в строку.

Преобразование набора узлов (состоящее из 1 или нескольких узлов) в строку выполняется путем объединения всех потомков текстовых узлов первого узла в наборе (*) . Поэтому использование . (или его более явная эквивалентная string(.) ) дает вам SENIOR ASSOCIATES окруженный кучей пробелов, потому что в вашем XML есть куча пробелов.

Чтобы избавиться от этого пробела, используйте функцию normalize-space() :

 //a[contains(normalize-space(.), 'SENIOR ASSOCIATES')] 

или, короче, потому что «текущий узел» является значением по умолчанию для этой функции:

 //a[contains(normalize-space(), 'SENIOR ASSOCIATES')] 

(*) Вот почему использование //a[contains(.//text(), 'SENIOR ASSOCIATES')] будет работать в первом из двух образцов выше, но не во втором.