Jak znaleźć element według klasy CSS za pomocą XPath?

296

Na mojej stronie znajduje divsię classnazwa Test.

Jak mogę to znaleźć XPath?

Truskawka
źródło
Bardziej ogólne powiązane rozwiązania XPath, CSS, DOM i Selenium można znaleźć w dokumencie XPath, CSS, DOM i Selenium: Kamień z Rosetty . W szczególności odpowiedź można znaleźć w identyfikatorze i nazwie przedmiotu .
Terence Xie,

Odpowiedzi:

472

Ten selektor powinien działać, ale będzie bardziej wydajny, jeśli zastąpisz go odpowiednim znacznikiem:

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

Lub, ponieważ wiemy, że poszukiwany element to div:

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

Ale ponieważ będzie to również pasować do przypadków takich jak class="Testvalue"lub class="newTest", wersja @ Tomalak podana w komentarzach jest lepsza :

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

Jeśli chcesz być naprawdę pewien, że będzie pasował poprawnie, możesz również użyć funkcji normalizacji spacji, aby usunąć zbłąkane białe znaki wokół nazwy klasy (jak wspomniano w @Terry):

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

Zauważ, że we wszystkich tych wersjach * należy najlepiej zastąpić dowolną nazwą elementu, który chcesz dopasować, chyba że chcesz wyszukać każdy element w dokumencie pod kątem danego warunku.

meder omuraliev
źródło
37
@meder: Bardziej jak //div[contains(concat(' ', @class, ' '), ' Test ')]- Twoi pojawią się również częściowe mecze.
Tomalak
5
Dlaczego nie zrobisz // div [@ class = 'Test']
Jessica,
11
Ponieważ klasy mogą zawierać więcej niż jedną wartość
meder omuraliev
8
Dziwi mnie, że xpath nie ma skrótu / bardziej wydajnego sposobu na zlokalizowanie tokena na liście tokenów oddzielonych spacjami. Coś w późniejszych wersjach Xpath?
thomasrutter
1
@ thomasrutter, dlaczego niespodzianka - to tylko język stworzony dla XML, a nie bardziej szczegółowy HTML, i kto powiedziałby, że swobodnie jest używać list rozdzielonych spacjami jako dowolnej wartości węzła w XML. Rozwiązanie Tomalaka jest bardzo realne.
bitoolean
152

Najłatwiejszy sposób ..

//div[@class="Test"]

Zakładając, że chcesz znaleźć <div class="Test">zgodnie z opisem.

Olli Puljula
źródło
3
Powyższa składnia jest dużo łatwiejsza w użyciu i mniej podatna na błędy. PAMIĘTAJ, że musisz mieć PODWÓJNE CYTATY wokół klasy, aby szukać. Polecam korzystanie z wymienionych powyżej. // div [@ class = "Test"]
FlyingV
Czy to działa w przypadkach, w których div [class = 'Test'] leży na głębszym poziomie?
Jake0x32
1
@ Jake0x32, to dlatego, że używa //nie tylko /.
Solomon Ucko
7
Czy pasuje również do `<div class =" Test some-other-class ">?
Jugal Thakkar
11
@JugalThakkar Nie, nie ma. Wymaga dokładnego dopasowania, ale możesz spróbować // div [zawiera (@class, „Test”)].
Olli Puljula
29

Tylko właściwy sposób to zrobić z XPath:

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

Funkcja normalize-spaceusuwa wiodące i końcowe białe znaki, a także zastępuje ciąg znaków białych znaków pojedynczą spacją.


Uwaga

Jeśli nie potrzebujesz wielu z tych zapytań Xpath, możesz użyć biblioteki, która konwertuje selektory CSS na XPath, ponieważ selektory CSS są zwykle o wiele łatwiejsze zarówno do odczytu, jak i zapisu niż zapytania XPath. Na przykład w tym przypadku można użyć obu div[class~="Test"]i div.Testuzyskać ten sam wynik.

Niektóre biblioteki, które udało mi się znaleźć:

John Slegers
źródło
24

Podaję to tylko jako odpowiedź, jak dawno temu Tomalak jako komentarz do odpowiedzi medera

//div[contains(concat(' ', @class, ' '), ' Test ')]
Alex Lyman
źródło
3
Przykro mi, że o tym wspomniałem z tamtych czasów, ale co powiesz concat(' ', normalize-space(@class), ' ')na wszystkie rodzaje białych znaków?
Terry
Ze względu na ciekawość - dlaczego //div[contains(concat(' ', @class, ' '), ' Test ')]/chidnie wybiera dzieci?
Fusion
@Fusion, jeśli opublikujesz to jako pytanie, możesz uzyskać odpowiedź.
bitoolean
@bitoolean bycie Kapitanem Cbvious jest obecnie trudne
Fusion
@Fusion Chciałem tylko pomóc. XPath nie jest językiem obsługującym HTML. Jest bardziej ogólny, tylko w języku XML. Nie mam w tym żadnego doświadczenia, ale myślę, że zakładasz, że możesz po prostu wstawić identyfikator zamiast tagu. Musisz wybrać wartość atrybutu „id”. Musisz więc pomyśleć o dokumencie HTML jako XML. Dyskusje poza tematem nie pomagają jednak znaleźć rozwiązań.
bitoolean
1

Pomocną funkcję można uzyskać z poprzednich odpowiedzi:

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

Następnie po prostu połącz wywołanie funkcji z zapytaniem.

Carcigenicate
źródło
Ten kod działałby tylko w PHP. Mogłeś o tym wspomnieć.
bitoolean
0

Dopasuj do jednej klasy, która ma spacje.

<div class="hello "></div>
//div[normalize-space(@class)="hello"]
Philip
źródło
-6

możesz znaleźć elementy takie jak ten przykład (wszystkie elementy css)

private By 
allElementsCss = By.xpath(".//div[@class]");
Siergiej Żyliński
źródło