How can I match on an attribute that contains a certain string?
当属性包含多个单词时,我在按属性选择节点时遇到问题。 例如:
这是我的xpath表达式:
//*[@class='atag']
表达式适用于
但不是前一个例子。 如何选择?
-
我认为值得指出的是,"atag btag"是一个属性,而不是两个属性。 你试图在xpath中进行子串匹配。
-
是的你是对的 - 这就是我想要的。
-
相关:stackoverflow.com/questions/8808921/和stackoverflow.com/questions/1604471/
-
这就是你应该使用CSS选择器... div.atag或div.btag的原因。 超级简单,不是字符串匹配,而且速度更快(在浏览器中得到更好的支持)。 XPath(针对HTML)应该降级为对包含文本和DOM导航查找元素有用的内容。
无论属性的位置如何,都将选择它们
1
| //div[contains(@class, 'atag') and contains(@class ,'btag')] |
-
@Redbeard:它是一个字面答案,但通常不是一个类匹配解决方案的目标。特别是它匹配,它包含目标字符串但不是具有给定类的div。
-
这适用于简单的场景 - 但要注意是否要在更广泛的上下文中使用此答案,而对正在检查的属性值的控制较少或无法控制。正确的答案是bobinces。
-
对不起,这与一个类不匹配,它匹配一个子字符串
-
它显然也是错误的:它不应该发现它。
-
问题是"包含某个字符串"而不是"匹配某个类"
mjv的答案是一个良好的开端,但如果atag不是列出的第一个类名,则会失败。
通常的方法是相当笨拙:
1
| //*[contains(concat(' ', @class, ' '), ' atag ')] |
只要类仅由空格分隔,而不是其他形式的空格,这就可以工作。几乎总是如此。如果它可能不是,你必须使它更加笨拙:
1
| //*[contains(concat(' ', normalize-space(@class), ' '), ' atag ')] |
(通过类名称的空格分隔字符串进行选择是一种常见的情况,令人惊讶的是没有特定的XPath函数,比如CSS3的'[class~ ="atag"]'。)
-
呸,xpath需要一些修复
-
下面的surupa123的答案要好得多,使用contains()只对你感兴趣的类,就我所见,不需要concats。
-
无法将tokenize,exists和index-of组合起来以一种相当丑陋但非常简洁的方式解决这个问题?
-
@Redbeard supra123s的答案是有问题的,如果你不想选择像"atagnumbertwo"这样的css类,虽然我承认这可能不太可能(:
-
@crazyrails:你能否接受这个答案作为正确的答案?这将有助于未来的搜索者找到问题描述的问题的正确解决方案。谢谢!
-
还没试过。但是,concnt只是在类属性的两边追加空格,如atag btag会变成 atag btag ,或者只是在每个类之前和之后追加空格,如 atag btag
-
这仍然是选择具有多个类的元素的最佳方法,还是已经进行了改进?
-
@ cha0site:是的,他们可以在XPath 2.0及以下版本中使用。这个答案是在XPath 2.0正式发布之前编写的。请参阅stackoverflow.com/a/12165032/423105或stackoverflow.com/a/12165195/423105
-
我想选择一个元素,如果它具有"列表"中的所有类,即应该同时具有atag和btag。我该怎么做呢 ?
-
@ testerjoe2:用and运算符?例如,对于XPath 1版本,[contains(..., atag ) and contains(..., btag )]
-
不要像我一样,删除你在这个例子中寻找的类周围的空间;它们实际上很重要。否则它可能会起作用但是会失败。
编辑:请参阅bobince的解决方案,该解决方案使用包含而不是启动,以及确保在完整令牌级别完成比较的技巧(以免'atag'模式被发现为另一个'标签'的一部分)。
"atag btag"是类属性的奇数值,但从不如此,请尝试:
1
| //*[starts-with(@class,"atag")] |
-
你可以使用这个,如果你的XPath引擎支持starts-with命令,例如JVM 6不支持它我记得
-
@mjv:CSS类属性常用于指定多个值。多数民众赞成如何完成CSS。
-
@mjv您不能保证该名称将出现在class属性的开头。
-
@thuktun @skaffman。谢谢,很棒的评论。我相应地重定向到bobince解决方案。
-
不适用于上述内容
试试这个://*[contains(@class, 'atag')]
一个有效的2.0 XPath:
1
| //*[tokenize(@class,'\s+')='atag'] |
或者使用变量:
1
| //*[tokenize(@class,'\s+')=$classname] |
-
如果@class有多个元素,这怎么办?因为它将返回一个单词列表,并将其与字符串进行比较失败,并且基数错误。
-
@AlexisWilke - 来自规范(w3.org/TR/xpath20/#id-general-comparisons):一般比较是存在量化的比较,可以应用于任何长度的操作数序列。它适用于我尝试过的每个2.0处理器。
-
另请注意,在XPath 3.1中,这可以简化为*[tokenize(@class)=$classname]
-
为了完整起见,如果你有幸使用模式感知的XPath处理器,并且@class有一个列表值类型,那么你可以简单地写*[@class=$classname]
请注意,如果您可以假设您感兴趣的类名不是另一个可能类名的子字符串,那么bobince的答案可能会过于复杂。如果是这样,您可以通过contains函数简单地使用子字符串匹配。以下内容将匹配其类包含子字符串'atag'的任何元素:
1
| //*[contains(@class,'atag')] |
如果上述假设不成立,则子字符串匹配将匹配您不想要的元素。在这种情况下,您必须找到单词边界。通过使用空格分隔符来查找类名边界,bobince的第二个答案找到完全匹配:
1
| //*[contains(concat(' ', normalize-space(@class), ' '), ' atag ')] |
这将匹配atag而不是matag。
-
这是我正在寻找的解决方案。 它清楚地在class = hello test world中找到test并且与hello test-test world不匹配。 由于我只使用XPath 1.0并且没有RegEx,因此这只是有效的解决方案。
添加到bobince的答案......
如果您使用的任何工具/库使用Xpath 2.0,您也可以这样做:
1
| //*[count(index-of(tokenize(@class, '\s+' ), $classname)) = 1] |
显然需要count()因为index-of()返回它在字符串中匹配的每个索引的序列。
-
我想你的意思是不要把$classname变量放在引号之间?因为它是一个字符串。
-
最后,getElementsByClassName的正确(JavasScript兼容)实现...当然除了字符串文字$classname。
-
这非常复杂。有关正确的XPath 2.0答案,请参阅@DanielHaleys响应。
您可以尝试以下方法
By.CssSelector("div.atag.btag")
对于包含公共URL的链接必须在变量中进行控制。然后按顺序尝试。
1 2 3 4 5 6
| 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();
} |