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


296

Na mojej stronie znajduje divsię classnazwa Test.

Jak mogę to znaleźć XPath?



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.


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.


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źć:


24

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

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

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.


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"]

-6

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

private By 
allElementsCss = By.xpath(".//div[@class]");
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.