【问题标题】:Create simple xpath expression with 'or' operator and a function使用“或”运算符和函数创建简单的 xpath 表达式
【发布时间】:2020-02-08 13:25:59
【问题描述】:

我可以让下面的 xpath 表达式更简单吗:

//*[translate(text(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' ,'abcdefghijklmnopqrstuvwxyz')='word1' or translate(text(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' ,'abcdefghijklmnopqrstuvwxyz')='word2']

上面做的不错,不过这么长,说不定有什么绝妙的办法。

我在考虑是否可以只放一次这个函数:

text() 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'

有可能吗?还是有其他方法?

【问题讨论】:

  • 虽然我从未尝试过翻译功能,但你可以尝试使用 contains() 可能吗。
  • 您没有用 XPath 版本标记它,但我猜它必须是 XPath 1.0,因为使用更高版本的 XPath,解决方案将是微不足道的。
  • 不,我想不出在 XPath 1.0 中更简单的方法。给 Selenium 的供应商打气,告诉他们您需要对 XPath 2.0 或者最好是 3.1 的支持。提醒他们,几周后 XPath 1.0 已经 20 岁了——为什么他们还在使用如此古老且早已被取代的东西?

标签: xml selenium xpath appium


【解决方案1】:

我可以让下面的 xpath 表达式更简单吗:

//*[translate(text(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' ,'abcdefghijklmnopqrstuvwxyz')='word1' 
   or translate(text(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' ,'abcdefghijklmnopqrstuvwxyz')='word2']

使用

//*[text()[starts-with(translate(., 'WORD', 'word'), 'word') 
          and substring(.,5) = 1 or substring(.,5) = 2]]

=================================

基于 XSLT 的验证

这种转变:

<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="//*[text()[starts-with(translate(., 'WORD', 'word'), 'word')
          and substring(.,5) = 1 or substring(.,5) = 2]]">
    <xsl:copy-of select="."/>
  </xsl:template>

  <xsl:template match="text()"/>
</xsl:stylesheet>

应用于此源 XML 文档时:

<t>
  <a>
    <b>Word2</b>
    <c>word3</c>
    <d>word1</d>
    <e>Word11</e>
    <f>Xxx</f>
  </a>
</t>

产生想要的、正确的结果——仅将匹配 XPath 表达式的元素复制到输出:

<b>Word2</b>
<d>word1</d>

更新:在评论中,OP 澄清说他想要一个 XPath 1.0 表达式来检查给定字符串是否是其他两个给定字符串之一。

这是在 XPath 1.0 中执行此操作的一种方法

contains(concat('|', $s1, '|', $s2, '|'), concat('|', $s, '|'))

我们检查给定字符串$s 的左+右连接是其他两个给定字符串$s1$s2 的连接中的子字符串(包含),因此相同的字符--@987654330 @ 是最左边、最右边和两个字符串之间的分隔符。

这里我们使用'|'作为分隔符,但任何已知不包含在$s 中的字符串都可以使用——例如?、$$$ 等。

那么上面已经提供的解决方案可以这样改写:

<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=
  "//*[text()[contains('|word1|word2|',
                        concat('|',translate(., 'WORD', 'word'), '|')
                       )]
       ]">
    <xsl:copy-of select="."/>
  </xsl:template>

  <xsl:template match="text()"/>
</xsl:stylesheet>

当此转换应用于同一个 XML 文档(上图)时,会产生相同的正确结果

<b>Word2</b>
<d>word1</d>

【讨论】:

  • 对不起,它没有回答这个问题。关键是我可以创建以下模式:text() 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' 'word1' or 'word2'。不重复翻译功能,但我可以使用搜索一些words。有可能吗?
  • @frianH 完全正确 这是在解决方案中完成的——translate() 仅使用一次。而长长的 ABCD--Z abcd--z 字符串不见了
  • @frianH,我想我现在明白你在问什么了。请在我的答案末尾查看更新——它提供了想要的解决方案。你能确认一下吗?
  • 太棒了,它奏效了。顺便问一下,您为什么提到 XPath 1.0?以后的版本是不是不同了,更简单了?
  • @frianH 在 XPath 2.0 或更高版本中可以简单地使用以下表达式:$s = ($s1, $s2)
【解决方案2】:

如果您正在检查这两个值的可见性,但是您尝试 iosNSPredicate 在这里尝试类似这样的操作 "type == \"XCUIElementTypeStaticText\" AND (name == \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" OR name == \"abcdefghijklmnopqrstuvwxyz\") ";

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多