如何使用XPath
表达式查找具有两个可能类名的元素?
我使用Selenium
在Python中工作,我希望找到class
具有两个可能名称之一的所有元素。
'//div[@class="list"]/div[@class="item ng-scope highlight"]//h3/a[@class="ng-binding"]'
当然,我可以进行两次单独的搜索,并将结果汇总到一个列表中。但是有一种更简单有效的方法。也许使用|
。
答案 0 :(得分:7)
您可以使用or
:
//div[@class="list"]/div[@class="item ng-scope highlight" or @class="item ng-scope"]//h3/a[@class="ng-binding"]
请注意,ng-scope
通常不是一个值得依赖的好类名,因为它是一个“纯技术”的AngularJS特定类(实际上与ng-binding
相同)是角元素所具有的。请查看是否使用contains()
并仅检查item
类是否足以涵盖用例:
//div[@class="list"]/div[contains(@class, "item")]//h3/a[@class="ng-binding"]
仅供参考,请注意您的案例中CSS选择器的简洁程度:
div.list > div.item h3 a
答案 1 :(得分:2)
接受的答案基本上不完整!
它的第二个表达式将匹配" item
",但也匹配" myitem3
" - 这不是想要的!
它的第一个表达式只找到" item ng-scope
"或" item ng-scope highlight
"在任何排列/重新排序的情况下,或者如果在类属性的值中存在任何其他空格,则不匹配。
我使用Selenium在Python中工作,我想找到所有元素 哪个类有两个可能的名称之一。 1.class ="项目范围突出显示" 2.class ="项目范围"
我认为除了这两个之外,您还希望将类属性的值覆盖为:
" ng-scope item"
"项目突出显示ng-scope"
" ng-scope项目突出显示"
"范围突出显示项目"
"突出显示项目范围"
"突出显示范围项"
并且,如果每个空格中有可变数量的空格" part",或者在sting的左端或右端,你最终会有无限多种可能性。 。
另一个松散点是:
除了想要的之外,class属性的值是否应该包含(仅)这些类名,还是允许它们包含其他类名?
根据上述问题的答案,可以有两种不同的解决方案,如下所示:
予。 class 属性除了想要的类名外还可以包含其他类名:
/div[contains(concat(' ', @class, ' '), ' list ')]
/div[contains(concat(' ', @class, ' '), ' item ')
and contains(concat(' ', @class, ' '), ' ng-scope ')]
II。 class 属性包含完全/仅包含所需的值:
//div[contains(normalize-space(@class) = 'list')]
/div[contains(concat(' ', @class, ' '), ' item ')
and contains(concat(' ', @class, ' '), ' ng-scope ')
and string-length(normalize-space(@class)) = 13
or
contains(concat(' ', @class, ' '), ' item ')
and contains(concat(' ', @class, ' '), ' ng-scope ')
and contains(concat(' ', @class, ' '), ' highlight ')
and string-length(normalize-space(@class)) = 23
]
以下是使用XSLT 的快速验证。转换评估XPath表达式并从每个表达式输出所选节点:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
Loose classes selection:
<xsl:copy-of select=
"//div[contains(concat(' ', @class, ' '), ' list ')]
/div[contains(concat(' ', @class, ' '), ' item ')
and contains(concat(' ', @class, ' '), ' ng-scope ')]
"/>
==============================
Exact number of classes selection:
<xsl:copy-of select=
"//div[contains(concat(' ', @class, ' '), ' list ')
and string-length(normalize-space(@class)) = 4
]
/div[contains(concat(' ', @class, ' '), ' item ')
and contains(concat(' ', @class, ' '), ' ng-scope ')
and string-length(normalize-space(@class)) = 13
or
contains(concat(' ', @class, ' '), ' item ')
and contains(concat(' ', @class, ' '), ' ng-scope ')
and contains(concat(' ', @class, ' '), ' highlight ')
and string-length(normalize-space(@class)) = 23
]
"/>
</xsl:template>
</xsl:stylesheet>
对以下文档应用此转换时:
<html>
<div class=" list class2 ">
<div class =" item ng-scope class3 "/>
<div class ="item ng-scope class4 "/>
<div class ="item ng-scope class5 "/>
<div class ="item ng-scope highlight class6 "/>
<div class =" highlight item class7 ng-scope "/>
</div>
<div class=" list ">
<div class =" item ng-scope "/>
<div class ="item ng-scope class4 "/>
<div class =" ng-scope item "/>
<div class ="item ng-scope highlight "/>
<div class =" highligh item ng-scope "/>
</div>
</html>
在两种情况下都会产生想要的正确结果:
Loose classes selection:
<div class=" item ng-scope class3 "/>
<div class="item ng-scope class4 "/>
<div class="item ng-scope class5 "/>
<div class="item ng-scope highlight class6 "/>
<div class=" highlight item class7 ng-scope "/>
<div class=" item ng-scope "/>
<div class="item ng-scope class4 "/>
<div class=" ng-scope item "/>
<div class="item ng-scope highlight "/>
<div class=" highligh item ng-scope "/>
==============================
Exact number of classes selection:
<div class=" item ng-scope "/>
<div class=" ng-scope item "/>
<div class="item ng-scope highlight "/>
XPath 2.0解决方案:
使用这两个XPath 2.0表达式:
<强>&#34;松散&#34;表达强>:
//div[contains(concat(' ', @class, ' '), ' list ')]
/div[every $token in ('item', 'ng-scope') satisfies $token = tokenize(@class, '\s+')[.]]
<强>&#34;精确&#34;表达强>:
//div[normalize-space(@class) = 'list']
/div[every $token in ('item', 'ng-scope') satisfies $token = tokenize(@class, '\s+')[.]
and not(tokenize(@class, '\s+')[.][3])
or
(every $token in ('item', 'ng-scope', 'highlight')
satisfies $token = tokenize(@class, '\s+')[.]
and not(tokenize(@class, '\s+')[.][4]))
]