Wie finde ich mit XPath ein Element nach CSS-Klasse?

Antworten:

472

Dieser Selektor sollte funktionieren, ist jedoch effizienter, wenn Sie ihn durch das entsprechende Markup ersetzen:

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

Oder, da wir wissen, dass das gesuchte Element a ist div:

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

Da dies jedoch auch mit Fällen wie class="Testvalue"oder class="newTest"übereinstimmt, ist die in den Kommentaren angegebene Version von @ Tomalak besser :

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

Wenn Sie wirklich sicher sein möchten, dass es korrekt übereinstimmt, können Sie auch die Funktion zum Normalisieren des Leerzeichens verwenden, um streunende Leerzeichen um den Klassennamen zu bereinigen (wie von @Terry erwähnt):

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

Beachten Sie, dass in all diesen Versionen das * am besten durch den Elementnamen ersetzt werden sollte, mit dem Sie tatsächlich übereinstimmen möchten, es sei denn, Sie möchten jedes einzelne Element im Dokument nach der angegebenen Bedingung durchsuchen.

meder omuraliev
quelle
37
@meder: Eher wie //div[contains(concat(' ', @class, ' '), ' Test ')]- Ihre werden auch teilweise Übereinstimmungen auftauchen.
Tomalak
5
Warum machst du nicht einfach // div [@ class = 'Test']
Jessica
11
Weil Klassen mehr als einen Wert enthalten können
meder omuraliev
8
Ich bin überrascht, dass xpath keine Verknüpfung / effizientere Möglichkeit hat, ein Token in einer durch Leerzeichen getrennten Tokenliste zu finden. Gibt es etwas in späteren Versionen von xpath?
Thomasrutter
1
@thomasrutter warum die Überraschung - dies ist nur eine Sprache für XML, nicht das spezifischere HTML, und wer sagt, dass es lässig ist, durch Leerzeichen getrennte Listen als Knotenwert in XML zu verwenden. Tomalaks Lösung ist sehr praktikabel.
Bitoolean
152

Einfachster Weg ..

//div[@class="Test"]

Angenommen, Sie möchten <div class="Test">wie beschrieben finden.

Olli Puljula
quelle
3
Die obige Syntax ist viel einfacher zu verwenden und weniger fehleranfällig. Denken Sie daran, dass Sie die DOPPELZITATE um die Klasse haben müssen, um suchen zu können. Ich würde empfehlen, die oben aufgeführten zu verwenden. // div [@ class = "Test"]
FlyingV
Funktioniert dies für die Fälle, in denen div [class = 'Test'] auf einer tieferen Ebene liegt?
Jake0x32
1
@ Jake0x32, das liegt daran, dass es //nicht nur verwendet /.
Solomon Ucko
7
Entspricht es auch `<div class =" Test some-other-class ">?
Jugal Thakkar
11
@JugalThakkar Nein, das tut es nicht. Es erfordert eine genaue Übereinstimmung, um zu funktionieren, aber Sie können stattdessen // div [enthält (@class, "Test")] versuchen.
Olli Puljula
29

Der EINZIGE richtige Weg, dies mit XPath zu tun:

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

Die Funktion entfernt normalize-spaceführende und nachfolgende Leerzeichen und ersetzt außerdem Sequenzen von Leerzeichen durch ein einzelnes Leerzeichen.


Hinweis

Wenn Sie nicht viele dieser Xpath-Abfragen benötigen, können Sie eine Bibliothek verwenden, die CSS-Selektoren in XPath konvertiert, da CSS-Selektoren in der Regel viel einfacher zu lesen und zu schreiben sind als XPath-Abfragen. In diesem Fall können Sie beispielsweise beide verwenden div[class~="Test"]und div.Testdas gleiche Ergebnis erzielen.

Einige Bibliotheken, die ich finden konnte:

John Slegers
quelle
24

Ich gebe dies nur als Antwort, wie Tomalak es vor langer Zeit als Kommentar zur Antwort von Meder gegeben hat

//div[contains(concat(' ', @class, ' '), ' Test ')]
Alex Lyman
quelle
3
Es tut mir leid, dass ich das von vor so langer Zeit angesprochen habe, aber was ist mit concat(' ', normalize-space(@class), ' ')der Berücksichtigung aller möglichen Leerzeichen?
Terry
Aus Neugier - Warum werden //div[contains(concat(' ', @class, ' '), ' Test ')]/chidkeine Kinder ausgewählt?
Fusion
@Fusion Wenn Sie dies als Frage posten, erhalten Sie möglicherweise eine Antwort.
Bitoolean
@bitoolean Captain Cbvious zu sein ist heutzutage schwer
Fusion
@Fusion Ich habe nur versucht zu helfen. XPath ist keine HTML-fähige Sprache. Es ist allgemeiner und nur XML. Ich habe keine Erfahrung damit, aber ich denke, Sie gehen davon aus, dass Sie einfach die ID anstelle des Tags einfügen können. Sie müssen den Wert des Attributs "id" auswählen. Sie müssen sich das HTML-Dokument also als XML vorstellen. Off-Topic-Diskussionen helfen den Leuten jedoch nicht, Lösungen zu finden.
Bitoolean
1

Eine hilfreiche Funktion kann aus früheren Antworten gemacht werden:

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

Dann konzentrieren Sie einfach den Funktionsaufruf in Ihre Abfrage.

Carcigenicate
quelle
Dieser Code würde nur in PHP funktionieren. Du hättest es erwähnen können.
Bitoolean
0

Match gegen eine Klasse mit Leerzeichen.

<div class="hello "></div>
//div[normalize-space(@class)="hello"]
Philip
quelle
-6

Sie können Elemente wie dieses Beispiel finden (alle CSS-Elemente)

private By 
allElementsCss = By.xpath(".//div[@class]");
Sergei Zhilinski
quelle