How can I match on an attribute that contains a certain string?

Xpath

Xpath Problem Overview


I am having a problem selecting nodes by attribute when the attributes contains more than one word. For example:

<div class="atag btag" />

This is my xpath expression:

//*[@class='atag']

The expression works with

<div class="atag" />

but not for the previous example. How can I select the <div>?

Xpath Solutions


Solution 1 - Xpath

Here's an example that finds div elements whose className contains atag:

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

Here's an example that finds div elements whose className contains atag and btag:

//div[contains(@class, 'atag') and contains(@class ,'btag')]

However, it will also find partial matches like class="catag bobtag".

If you don't want partial matches, see bobince's answer below.

Solution 2 - Xpath

mjv's answer is a good start but will fail if atag is not the first classname listed.

The usual approach is the rather unwieldy:

//*[contains(concat(' ', @class, ' '), ' atag ')]

this works as long as classes are separated by spaces only, and not other forms of whitespace. This is almost always the case. If it might not be, you have to make it more unwieldy still:

//*[contains(concat(' ', normalize-space(@class), ' '), ' atag ')]

(Selecting by classname-like space-separated strings is such a common case it's surprising there isn't a specific XPath function for it, like CSS3's '[class~="atag"]'.)

Solution 3 - Xpath

try this: //*[contains(@class, 'atag')]

Solution 4 - Xpath

EDIT: see bobince's solution which uses contains rather than start-with, along with a trick to ensure the comparison is done at the level of a complete token (lest the 'atag' pattern be found as part of another 'tag').

"atag btag" is an odd value for the class attribute, but never the less, try:

//*[starts-with(@class,"atag")]

Solution 5 - Xpath

A 2.0 XPath that works:

//*[tokenize(@class,'\s+')='atag']

or with a variable:

//*[tokenize(@class,'\s+')=$classname]

Solution 6 - Xpath

Be aware that bobince's answer might be overly complicated if you can assume that the class name you are interested in is not a substring of another possible class name. If this is true, you can simply use substring matching via the contains function. The following will match any element whose class contains the substring 'atag':

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

If the assumption above does not hold, a substring match will match elements you don't intend. In this case, you have to find the word boundaries. By using the space delimiters to find the class name boundaries, bobince's second answer finds the exact matches:

//*[contains(concat(' ', normalize-space(@class), ' '), ' atag ')]

This will match atag and not matag.

Solution 7 - Xpath

To add onto bobince's answer... If whatever tool/library you using uses Xpath 2.0, you can also do this:

//*[count(index-of(tokenize(@class, '\s+' ), $classname)) = 1]

count() is apparently needed because index-of() returns a sequence of each index it has a match at in the string.

Solution 8 - Xpath

You can try the following

By.CssSelector("div.atag.btag")

Solution 9 - Xpath

I came here searching solution for Ranorex Studio 9.0.1. There is no contains() there yet. Instead we can use regex like:

div[@class~'atag']

Solution 10 - Xpath

For the links which contains common url have to console in a variable. Then attempt it sequentially.

webelements allLinks=driver.findelements(By.xpath("//a[contains(@href,'http://122.11.38.214/dl/appdl/application/apk')]"));
int linkCount=allLinks.length();
for(int i=0; <linkCount;i++)
{
	driver.findelement(allLinks[i]).click();
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioncrazyrailsView Question on Stackoverflow
Solution 1 - Xpathsurupa123View Answer on Stackoverflow
Solution 2 - XpathbobinceView Answer on Stackoverflow
Solution 3 - XpathSelenUserView Answer on Stackoverflow
Solution 4 - XpathmjvView Answer on Stackoverflow
Solution 5 - XpathDaniel HaleyView Answer on Stackoverflow
Solution 6 - XpathBrent AtkinsonView Answer on Stackoverflow
Solution 7 - Xpatharmyofda12mnkeysView Answer on Stackoverflow
Solution 8 - XpathUmesh ChhabraView Answer on Stackoverflow
Solution 9 - XpathJarno ArgillanderView Answer on Stackoverflow
Solution 10 - Xpathuser3906232View Answer on Stackoverflow