Как я могу найти элемент по классу CSS с XPath?

297

В моей странице, есть divс classименем Test.

Как я могу найти это с XPath?

клубника
источник
Более общие решения XPath, CSS, DOM и Selenium можно найти в документе XPath, CSS, DOM и Selenium: The Rosetta Stone . В частности, ваш ответ можно найти в пункте Id & Name .
Теренс Се

Ответы:

473

Этот селектор должен работать, но будет более эффективным, если вы замените его подходящей разметкой:

//*[contains(@class, 'Test')]

Или, поскольку мы знаем, что искомый элемент является div:

//div[contains(@class, 'Test')]

Но так как это также будет соответствовать случаям, подобным class="Testvalue"или class="newTest", версия @ Tomalak, предоставленная в комментариях, лучше :

//div[contains(concat(' ', @class, ' '), ' Test ')]

Если вы хотите быть действительно уверены, что оно будет соответствовать правильно, вы также можете использовать функцию normalize-space для очистки случайных пробельных символов вокруг имени класса (как упомянуто @Terry):

//div[contains(concat(' ', normalize-space(@class), ' '), ' Test ')]

Обратите внимание, что во всех этих версиях * лучше всего заменить на любое имя элемента, которому вы действительно хотите соответствовать, если только вы не хотите искать каждый элемент в документе для заданного условия.

медер омуралиев
источник
37
@meder: Больше похоже //div[contains(concat(' ', @class, ' '), ' Test ')]- у вас тоже будут частичные совпадения.
Томалак
5
Почему бы вам просто не сделать // div [@ class = 'Test']
Джессика
11
Потому что классы могут содержать более одного значения
meder omuraliev
8
Я удивлен, что у xpath нет быстрого / более эффективного способа найти токен в списке разделенных пробелами токенов. Что-нибудь в более поздних версиях xpath?
Томасруттер
1
@thomasrutter почему сюрприз - это всего лишь язык, созданный для XML, а не более конкретный HTML, и кто скажет, что использование разделенных пробелами списков в качестве любого значения узла в XML непривычно. Решение Томалака очень жизнеспособное.
bitoolean
152

Самый простой способ ..

//div[@class="Test"]

Предполагая, что вы хотите найти, <div class="Test">как описано.

Олли Пулюла
источник
3
Приведенный выше синтаксис намного проще в использовании и менее подвержен ошибкам. ПОМНИТЕ, что вам нужно иметь ДВОЙНЫЕ ЦИТАТЫ вокруг класса для поиска. Я бы порекомендовал использовать перечисленные выше. // div [@ class = "Test"]
FlyingV
Работает ли это для случаев, когда div [class = 'Test'] находится на более глубоком уровне?
Jake0x32
1
@ Jake0x32, это потому, что он использует //не только /.
Соломон Уко
7
Это также соответствует `<div class =" Test some-other-class ">?
Джугал Тхаккар
11
@JugalThakkar Нет, это не так. Для работы требуется точное совпадение, но вместо этого вы можете попробовать // div [Содержит (@class, "Test")].
Олли Пулюла
29

Только правильный способ сделать это с помощью XPath:

//div[contains(concat(" ", normalize-space(@class), " "), " Test ")]

Функция normalize-spaceудаляет начальные и конечные пробелы, а также заменяет последовательности пробельных символов одним пробелом.


Заметка

Если вам не нужны многие из этих запросов Xpath, вы можете использовать библиотеку, которая преобразует селекторы CSS в XPath, поскольку селекторы CSS обычно намного проще читать и писать, чем запросы XPath. Например, в этом случае вы можете использовать оба div[class~="Test"]и div.Testполучить одинаковый результат.

Некоторые библиотеки, которые мне удалось найти:

Джон Слегерс
источник
24

Я просто представляю это как ответ, как Томалак давал в качестве комментария к ответу медика давным-давно

//div[contains(concat(' ', @class, ' '), ' Test ')]
Алекс Лиман
источник
3
Извините, что поднял этот вопрос с того времени, но как насчет concat(' ', normalize-space(@class), ' ')учета всевозможных пробелов?
Терри
Ради любопытства - почему //div[contains(concat(' ', @class, ' '), ' Test ')]/chidне выбирают детей?
Fusion,
@Fusion, если вы разместите это как вопрос, вы можете получить ответ.
bitoolean
@bitoolean быть капитаном Cbvious трудно в эти дни
Fusion
@ Фьюжн Я просто пытался помочь. XPath не является языком, поддерживающим HTML. Это более общий, только для XML. У меня нет никакого опыта в этом, но я думаю, вы предполагаете, что можете просто поставить идентификатор вместо тега. Вам нужно выбрать значение атрибута "id". Поэтому вам нужно думать о HTML-документе как о XML. Вне темы обсуждения не помогают людям найти решения, хотя.
bitoolean
1

Полезная функция может быть сделана из предыдущих ответов:

function matchClass($className) {
    return "[contains(concat(' ', normalize-space(@class), ' '), ' $className ')]";
}

Затем просто включите вызов функции в ваш запрос.

Carcigenicate
источник
Этот код будет работать только на PHP. Вы могли бы упомянуть об этом.
bitoolean
0

Матч против одного класса, который имеет пробел.

<div class="hello "></div>
//div[normalize-space(@class)="hello"]
Филипп
источник
-6

Вы можете найти элементы, подобные этому примеру (все элементы CSS)

private By 
allElementsCss = By.xpath(".//div[@class]");
Сергей Жилинский
источник