XPath: Как выбрать элементы на основе их стоимости?

221

Я новичок в использовании XPath, и это может быть основным вопросом. Пожалуйста, потерпите меня и помогите мне решить проблему. У меня есть XML-файл, как это:

<RootNode>
  <FirstChild>
    <Element attribute1="abc" attribute2="xyz">Data</Element>
  <FirstChild>
</RootNode>

Я могу проверить наличие <Element>тега с помощью:

// Элемент [@ attribute1 = "abc" и @ attribute2 = "xyz"]

Теперь я также хочу проверить значение тега для строки "Data". Для достижения этого мне сказали использовать:

// Элемент [@ attribute1 = "abc" и @ attribute2 = "xyz" и данные]

Когда я использую более позднее выражение, я получаю следующую ошибку:

Сообщение об ошибке подтверждения: не найдено ни одного узла //Element[@attribute1="abc" and @attribute2="xyz" and Data]

Пожалуйста, дайте мне ваш совет, является ли правильное выражение XPath, которое я использовал. Если нет, то каким будет действительное выражение XPath?

vcosk
источник

Ответы:

329

Условие ниже:

//Element[@attribute1="abc" and @attribute2="xyz" and Data]

проверяет наличие элемента данных внутри элемента, а не значения элемента данных.

Вместо этого вы можете использовать

//Element[@attribute1="abc" and @attribute2="xyz" and text()="Data"]
SO User
источник
25
//Element[@attribute1="abc" and @attribute2="xyz" and .="Data"]

Причина, по которой я добавляю этот ответ, заключается в том, что я хочу объяснить взаимосвязь .и text().

Первое, что при использовании [], есть только два типа данных:

  1. [number] выбрать узел из набора узлов
  2. [bool] фильтровать набор узлов из набора узлов

В этом случае значение оценивается как логическое по функции boolean(), и существует правило:

Фильтры всегда оцениваются с учетом контекста.

Когда вам нужно сравнить text()или .со строкой "Data", он сначала использует string()функцию для преобразования их в строковый тип, а затем получает логический результат.

Есть два важных правила string():

  1. string()Функция преобразует набор узлов в строку, возвращая строковое значение первого узла в наборе узлов, который в некоторых случаях может привести к непредсказуемым результатам.

    text()это относительный путь, который возвращает набор узлов, содержащий весь текстовый узел текущего узла (контекстного узла), например ["Data"]. Когда он оценивается string(["Data"]), он возвращает первый узел набора узлов, поэтому вы получаете «Данные» только тогда, когда в наборе узлов есть только один текстовый узел.

  2. Если вы хотите, чтобы string()функция объединила весь дочерний текст, вы должны затем передать один узел вместо набора узлов.

    Например, мы получаем набор узлов ['a', 'b'], вы можете передать туда родительский узел string(parent), он вернется 'ab', и string(.)в вашем случае, конечно, вернет объединенную строку "Data".

В обоих случаях результат будет одинаковым только при наличии текстового узла.

宏杰 李
источник