Selecting a CSS class with XPath

While looking for a way to select a CSS class with XPath in a reliable way. I came across many solutions, and while they felt obvious, they were flawed as well. So lets start with the most reliable way I found so far.

How do you do this in XPath?

XPath doesn’t have a native equivalent of a CSS class selector. Where .className will select any element that has the class className. The closest equivalent is:

//*[contains(concat(" ", normalize-space(@class), " "), " className ")]

The function normalize-space strips leading and trailing whitespace and also replaces sequences of whitespace characters by a single space.

Similiarly it is equivalent to the CSS selector:

*[class~="className"]

which will match any element whose class attribute value is a list of whitespace-separated values, one of which is exactly equal to className.

The obvious but wrong ways to do it

The XPath selector:

//*[@class="className"]

doesn’t work because it won’t match an element that has more than one class, for example

<div class="className anotherClassName">

It also won’t match if there is any extra whitespace around the class name:

<div class=" className  ">

The ‘improved’ XPath selector:

//*[contains(@class, "className")]

doesn’t work either because it wrongly matches elements with the class classNameTwo, for example:

<div class="classNameTwo">