Что содержит () в XPath?

У меня есть две почти идентичные таблицы, единственное отличие заключается в входном теге в первой:

Таблица 1

  <table>
    <tbody>
      <tr>
        <td>
          <div>
            <input type="text" name="" value=""/>
          </div>
        </td>
      </tr>
    </tbody>
  </table>

Таблица 2

  <table>
    <tbody>
      <tr>
        <td>
          <div></div>
        </td>
      </tr>
    </tbody>
  </table>
</body>

Когда я использую этот XPath //table//tbody//tr[position()=1 and contains(.,input)] он возвращает первую строку обеих таблиц, а не только первую строку первой таблицы, как я и ожидал.

Однако этот XPath //table//tbody//tr[position()=1]//input возвращает только input в первом.

Итак, что я делаю не так? Почему то же самое input связано с обеими таблицами? Я неправильно использую . здесь как-то?

2 ответа

Решение

Из-за неудачного выбора названий функций 1 многие люди ошибочно принимают contains() функция в XPath:

  • XPath contains() не проверяет наличие элементов.
  • XPath contains() проверяет наличие подстроки.

Следовательно, tr[contains(.,input)] не делает то, что вы думаете, что делает. Это на самом деле выбирает tr элементы, строковое значение которых содержит подстроку, равную строковому значению первого непосредственного дочернего элемента input элемент; см. этот ответ для более подробной информации. (Интересно, что такой предикат упрощается до истины, поскольку иерархическая природа определения строкового значения подразумевает содержание подстроки между строковыми значениями родительских и дочерних элементов.) В любом случае, это явно не ваше намерение.

Чтобы проверить наличие элемента- потомка, используйте .//input вместо. Это может быть помещено как предикат tr как ваш первый XPath попытался сделать, если это tr элементы, которые вы хотите выбрать,

//table//tbody//tr[position()=1 and .//input]

или же table ( как показано @Andersson), если это действительно table элементы, которые вы хотите выбрать, которые содержат input потомок элемента:

//table[.//input]

Почему XPath contains() должен был быть назван string-contains()

1 В контексте XML, который так сильно основан на понятии иерархии, естественно предположить, что содержание относится к иерархическому сдерживанию. Из 24 раз слово содержит появляется в исходной спецификации XPath, 19 раз это означает содержание иерархического узла; только 5 раз это означает сохранение подстроки. Неудивительно, что путаница над contains() существует. Подстрока XPath contains() функция должна была иметь имя string-contains ().

Тебе стоит попробовать

//table[.//input]

принести table узел, который имеет input потомок

Другие вопросы по тегам