ChatGPT解决这个技术问题 Extra ChatGPT

How can I find an element by CSS class with XPath?

In my webpage, there's a div with a class named Test.

How can I find it with XPath?

The more general related XPath,CSS, DOM and Selenium Solutions can be found in document XPath, CSS, DOM and Selenium: The Rosetta Stone. Specifically, your answer can be found in the item Id & Name.

T
Teemu Leisti

This selector should work but will be more efficient if you replace it with your suited markup:

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

Or, since we know the sought element is a div:

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

But since this will also match cases like class="Testvalue" or class="newTest", @Tomalak's version provided in the comments is better:

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

If you wished to be really certain that it will match correctly, you could also use the normalize-space function to clean up stray whitespace characters around the class name (as mentioned by @Terry):

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

Note that in all these versions, the * should best be replaced by whatever element name you actually wish to match, unless you wish to search each and every element in the document for the given condition.


@meder: More like //div[contains(concat(' ', @class, ' '), ' Test ')] - Yours will turn up partial matches as well.
Why don't you just do //div[@class='Test']
Because classes can contain more than one value
I'm surprised xpath doesn't have a shortcut/more efficient way to locate a token in a space-separated token list. Anything in later versions of xpath?
@thomasrutter why the surprise - this is just a language made for XML, not the more specific HTML, and who's to say it's casual to use space-separated lists as any node value in XML. Tomalak's solution is a very viable one.
W
Will Tate

Most easy way..

//div[@class="Test"]

Assuming you want to find <div class="Test"> as described.


The above syntax is a lot easier to use and is less error-prone. REMEMBER you need to have the DOUBLE QUOTES around the class to search. I would recommend using the listed above. //div[@class="Test"]
@Jake0x32, that's because it uses // not just /.
Does it match `
too?
@JugalThakkar No, it doesn't. It requires an exact match to work but you can try //div[contains(@class,"Test")] instead.
This answer may benefit from further clarification as it doesn't really answer the OP's question. OP says "a div with a class named Test", but at no point it is suggested that "Test" is the only class in the div, which is what this answer assumes. The simplicity of this answer is appealing, which could lure readers into trouble.
J
John Slegers

The ONLY right way to do it with XPath :

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

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

Note

If not need many of these Xpath queries, you might want to use a library that converts CSS selectors to XPath, as CSS selectors are usually a lot easier to both read and write than XPath queries. For example, in this case, you could use the selector div.Test to get the exact same result.

Some libraries I've been able to find :

For JavaScript : css2xpath & css-to-xpath

For PHP : CssSelector Component

For Python : cssselect

For C# : css2xpath Reloaded

For GO : css2xpath


this is REALLY the only way to avoid issues e.g. if you have more than one class assigned!
How about //div[@class[contains(.,'Test')]]?
A
Alex Lyman

I'm just providing this as an answer, as Tomalak provided as a comment to meder's answer a long time ago

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

Sorry to bring this up from such a time ago but what about concat(' ', normalize-space(@class), ' ') to account for all sorts of white-space characters as well?
For a sake of curiosity - Why //div[contains(concat(' ', @class, ' '), ' Test ')]/chid does not select children?
@Fusion if you post that as a question, you might get an answer.
@bitoolean being Captain Cbvious is hard these days
@Fusion I was just trying to help. XPath is not an HTML-aware language. It's more generic, XML-only. I don't have any experience in it, but I think you're assuming you can just put the id instead of the tag. You need to select on the "id" attribute's value. So you need to think of the HTML document as XML. Off-topic discussions don't help people find solutions though.
B
Bennett McElwee

XPath has a contains-token function, specifically designed for this situation:

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

It's only supported in the latest version of XPath (3.1) so you'll need an up-to-date implementation.


XPath 3.1, per your link.
Yes, it was added in version 3.1. The W3C have a nice 3.0-3.1 diff. I have updated the answer.
S
Siebe Jongebloed

Since XPath 2.0 there is a tokenize-function you can use:

//div[tokenize(@class,'\s+')='Test']

Here it will tokenize on white-space and then compares the resulting strings with 'Test'.

It's an alternative of the XPath 3.1 function contains-token()

But at this moment (2021-04-30) no browser support XPath 2.0 or more.


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

This is what I am using in my current project and it works smooth as.

The dot . in the expression represents the value of class attribute of any div element. So you don't need to use normalize-space and concat. Note this might also select divs with classnames XXXTestXXX. I happen to have my searchable class as infobox-header and the page doesn't have anything like XXinfobox-headerXXXX.


P
Philip

Match against one class that has whitespace.

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