带有not()和ends-with()的Xpath错误

时间:2011-05-29 11:17:37

标签: java xpath selenium-webdriver

我有以下Xpath表达式:

//*[not(input)][ends-with(@*, 'Copyright')]

我希望它能给我所有元素 - 输入除外 - 任何以“Copyright”结尾的属性值。

我在webDriver.findElements(By.xpath(expression))的Selenium 2 Java API中执行它并收到以下错误:

  

表达不合法   表达

但这些表达没有问题:

//*[not(input)][starts-with(@*, 'Copyright')]
//*[ends-with(@*, 'Copyright')]

有什么想法吗?

4 个答案:

答案 0 :(得分:5)

  

我有以下Xpath表达式:

//*[not(input)][ends-with(@*, 'Copyright')]
     

我希望它能给我所有元素 -   输入除外 - 具有任何属性   以“Copyright”结尾的值。

这里有一些问题

  1. ends-with()仅是一个标准的XPath 2.0函数,因此您可能正在使用XPath 1.0引擎并且它正确引发错误,因为它不知道名为{{1}的函数}。

  2. 即使您使用的是XPath 2.0处理器,表达式ends-with()也会导致一般情况下的错误,因为ends-with(@*, 'Copyright')函数被定义为接受最多一个字符串({ {1}})作为两个操作数 - 但是当元素具有多个属性时,ends-with()会生成一个包含多个字符串的序列。

  3. xs:string?并不意味着“选择所有未命名为@*的元素。真正的含义是:”选择所有没有名为“input”的子元素的元素。< / p>

  4. <强>解决方案

    1. 使用此XPath 2.0表达式://*[not(input)]

    2. 对于XPath 1.0,请使用以下表达式:

    3. ...

      input

      以下是使用XSLT对上一个XPath表达式进行简短而完整的验证:

      //*[not(self::input)][@*[ends-with(.,'Copyright')]]

      将此转换应用于以下XML文档时:

        //*[not(self::input)]
              [@*[substring(., string-length() -8) = 'Copyright']]
      

      产生了想要的正确结果

      <xsl:stylesheet version="1.0"
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
       <xsl:output omit-xml-declaration="yes" indent="yes"/>
       <xsl:strip-space elements="*"/>
      
       <xsl:template match="/*">
           <xsl:copy-of select=
           "//*[not(self::input)]
                 [@*[substring(., string-length() -8)
                    = 'Copyright'
                    ]
                ]"/>
       </xsl:template>
      </xsl:stylesheet>
      

      如果XML文档位于默认命名空间

      <html>
       <input/>
       <a x="Copyright not"/>
       <a y="This is a Copyright"/>
      </html>
      

      应用于此XML文档时

      <a y="This is a Copyright"/>
      

      产生了想要的正确结果:

      <xsl:stylesheet version="1.0"
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
       xmlns:x="http://www.w3.org/1999/xhtml"
       >
       <xsl:output omit-xml-declaration="yes" indent="yes"/>
       <xsl:strip-space elements="*"/>
      
       <xsl:template match="/*">
           <xsl:copy-of select=
           "//*[not(self::x:input)]
                 [@*[substring(., string-length() -8)
                    = 'Copyright'
                    ]
                ]"/>
       </xsl:template>
      </xsl:stylesheet>
      

答案 1 :(得分:1)

我不知道Selenium但是如果成功解析//*[not(input)][starts-with(@*, 'Copyright')]并且另外支持XPath 2.0函数ends-with那么我看不出为什么//*[not(input)][ends-with(@*, 'Copyright')]不被接受的原因作为一种法律表达。然而,您的口头描述听起来好像是//*[not(self::input)][@*[ends-with(., 'Copyright')]]

//*[not(input)]选择任何没有任何输入子元素的元素,而//*[not(self::input)]选择任何不属于自己input元素的元素。至于将[@*[ends-with(., 'Copyright')]]与你所拥有的进行比较,我的建议是正确的,只要有任何属性节点以“版权”结尾,而你的测试只有在有一个以“版权”结尾的单一属性时才有效,作为ends-with http://www.w3.org/TR/xquery-operators/#func-ends-with允许带有单个项目的序列作为其第一个参数或空序列而不是多个项目。

答案 2 :(得分:0)

最可能的解释是您使用的是XPath 1.0处理器。 ends-with()函数需要XPath 2.0支持。

答案 3 :(得分:0)

//*[not(self::input)][@*[substring(., string-length(.) -8) = 'Copyright']]

使用string-length(.)

进行小幅修正

现在,它可能有用。