如何匹配包含特定字符串的属性?

当属性包含多个单词时,我有一个按属性选择节点的问题。例如:

<div class="atag btag" />

这是我的xpath表达式:

//*[@class='atag']

这个表达式适用于

<div class="atag" />

但对于前面的例子不是这样。如何选择<div>?

418866 次浏览

编辑:参见bobince的解决方案,它使用包含而不是开始,以及一个技巧,以确保比较是在一个完整的标记级别上完成的(以免'atag'模式被发现为另一个'标签'的一部分)。

"atag btag"是class属性的奇数值,但无论如何,尝试:

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

Mjv的答案是一个很好的开始,但如果atag不是列出的第一个类名,则会失败。

通常的方法相当笨拙:

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

只要类之间仅用空格分隔,而不是其他形式的空格,这种方法就有效。情况几乎总是如此。如果它可能不是,你必须让它变得更笨拙:

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

(通过类名一样的空格分隔字符串进行选择是非常常见的情况,令人惊讶的是它没有特定的XPath函数,比如CSS3的'[class~="atag"]'。)

下面是一个找到className包含atag的div元素的例子:

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

下面是一个例子,查找className包含atagbtag的div元素:

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

然而,它也会找到像class="catag bobtag"这样的部分匹配。

如果你不想要部分匹配,请看下面bobince的答案。

添加到bobince的答案… 如果您使用的工具/库使用Xpath 2.0,也可以这样做:

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

Count()显然是必需的,因为index-of()返回字符串中与之匹配的每个索引的序列。

工作的2.0 XPath:

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

或者用一个变量:

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

试试这个://*[contains(@class, 'atag')]

你可以试试下面的方法

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

注意,bobince的答案可能过于复杂,如果你可以假设您感兴趣的类名不是另一个可能的类名的子字符串。如果这是真的,您可以通过contains函数简单地使用子字符串匹配。下面将匹配任何类包含子字符串'atag'的元素:

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

如果上面的假设不成立,子字符串匹配将匹配您不打算匹配的元素。在这种情况下,你必须找到单词边界。通过使用空格分隔符找到类名边界,bobince的第二个答案找到了精确的匹配:

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

这将匹配atag而不是matag

对于包含公共url的链接,必须在变量中控制台。然后按顺序尝试。

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();
}

我来这里寻找Ranorex Studio 9.0.1的解决方案。这里还没有contains()。相反,我们可以像这样使用regex:

div[@class~'atag']