如何通过XPath查找具有两个可能类名的元素?

时间:2016-02-11 16:27:39

标签: python selenium xpath

如何使用XPath表达式查找具有两个可能类名的元素?

我使用Selenium在Python中工作,我希望找到class具有两个可能名称之一的所有元素。

  1. class =" item ng-scope highlight"
  2. class =" item ng-scope"
  3. '//div[@class="list"]/div[@class="item ng-scope highlight"]//h3/a[@class="ng-binding"]'

    当然,我可以进行两次单独的搜索,并将结果汇​​总到一个列表中。但是有一种更简单有效的方法。也许使用|

2 个答案:

答案 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]))
          ]