【问题标题】:Xpath expression error due to apostrophe in a String in robot framework由于机器人框架中字符串中的撇号导致的 Xpath 表达式错误
【发布时间】:2017-10-17 09:30:26
【问题描述】:

我在机器人框架脚本中遇到以下错误。

InvalidSelectorException: Message: invalid selector: Unable to locate an element with the xpath expression //ul[@id='xyz-ul']/li[contains(text(),'Épargne en vue d\'un objectif précis')] because of the following error:
SyntaxError: Failed to execute 'evaluate' on 'Document': The string '//ul[@id='xyzul']/li[contains(text(),'Épargne en vue d\'un objectif précis')]' is not a valid XPath expression.

我正在尝试从 excel 中获取法语数据 "Épargne en vue d'un objectif précis" 并传入 xpath 以识别和单击元素。

该元素是一个下拉菜单。这是场景之一。我还有很多其他这样的场景都失败了。有人可以帮忙解决这个问题吗?

【问题讨论】:

    标签: xpath robotframework dropdown


    【解决方案1】:

    XPath 没有转义序列。

    //ul[@id='xyz-ul']/li[contains(text(),'Épargne en vue d\'un objectif précis')]
    

    一样无效
    //ul[@id='xyz-ul']/li[contains(text(),'Épargne en vue d'un objectif précis')]
    

    会的。

    这取决于您是否可以减轻此错误或您是否不走运。

    在测试框架的上下文中,您可能很不走运,但您需要展示更多代码以获得更好的答案。


    在 XPath 中有两种方法可以将单引号放入字符串中。

    1. 对字符串使用双引号。然后你可以在里面使用单引号(反之亦然)。

      //ul[@id='xyz-ul']/li[contains(text(),"Épargne en vue d'un objectif précis")]
      
    2. 当这不可行时,例如在您的情况下,因为您永远不知道用户提供的值是包含单引号还是双引号,您必须像这样使用concat() XPath 函数:

      //ul[@id='xyz-ul']/li[contains(text(), concat('Épargne en vue d', "'", 'un objectif précis'))]
      

    第二个版本看起来很困难,但实际上可以通过拆分和连接输入字符串来可靠地构建它,就像这样

    1. 输入字符串为Épargne en vue d'un objectif précis
    2. ' 处拆分得到Épargne en vue dun objectif précis
    3. 加入', "'", ' 会得到Épargne en vue d', "'", 'un objectif précis
    4. concat('') 包裹会得到concat('Épargne en vue d', "'", 'un objectif précis')

    这正是您可以使用占位符放入 XPath 表达式的字符串,如下所示:

    ${dropdown_selection_first_part_xpath} =  //ul[@id='xyz-ul']/li[contains(text(), 
    ${dropdown_selection_second_part_xpath} =  )]
    ${dropdown_xpath} =  //div[@id='xyz-widget']/div/div[2]/div[1]
    
    ${escaped_input_purpose_of_account} = (somehow to the 4 steps above)
    
    ${dropdown_selection_xpath} =  catenate  SEPARATOR=            ${dropdown_selection_first_part_xpath}    ${escaped_input_purpose_of_account}    ${dropdown_selection_second_part_xpath}
    

    这种方法适用于所有输入(空字符串、不带引号的字符串、带有单引号和双引号的任意组合的字符串),并且始终创建符合您期望的语法有效的 XPath。

    【讨论】:

    • 我已经尝试过您的第二个选项,但没有成功。我已经发布了其余的代码作为答案。
    • 查看更新的答案。如果您能弄清楚如何执行框架中描述的四个步骤,那么您很幸运。如果你的框架由于某种原因不能这样做,那么你就不能使用带单引号的测试字符串。
    【解决方案2】:

    正如另一个答案中所说的那样,xpath 中没有转义引号。您可以采取的解决方法是使用相反的引号类型来包围文本字符串。

    所以对于问题中的示例,这 - 双引号 - 应该这样做:

    //ul[@id='xyz-ul']/li[contains(text(),"Épargne en vue d'un objectif précis")]
    

    现在,您的一些测试字符串可能有单引号,其他的 - 双引号。这是她如何构建正确的定位器的示例代码,每个案例:

    ${dropdown_selection_first_part_xpath} =  //ul[@id='xyz-ul']/li[contains(text(),  # no quote symbol
    ${dropdown_selection_second_part_xpath} =  )]  # no symbol here also
    ${dropdown_xpath} =  //div[@id='xyz-widget']/div/div[2]/div[1]
    
    # "Get Value" omitted for brevity, no change in it
    
    Enter Value
        click element  xpath=${dropdown_xpath} 
        ${input}=  Get Value  ${language}
    
        # put the surrounding quotes based on the string's content - double quotes if it has a single one, single otherwise
        ${input}=  Set Variable If    "'" in """${input}"""    "${input}"    '${input}'
    
        ${dropdown_selection_xpath}=  catenate  SEPARATOR=        ${dropdown_selection_first_part_xpath}  ${input}  ${dropdown_selection_second_part_xpath}
        click element  xpath=${dropdown_selection_xpath}
    

    最后,如果您有带单引号和双引号的测试字符串 - 这会更棘手,但仍然可行。

    【讨论】:

    • 只要在同一个字符串中有单引号和双引号,它就会分开。我的回答中描述的方法几乎是在不创建在某些输入处中断的代码的情况下做到这一点的唯一方法。
    • 自引用 - “最后,如果你有带单引号和双引号的测试字符串 - 这会更棘手,但仍然可行。”暗示 - 虽然是的,但没有明确说明,这不适用于混合引号源字符串。
    • 这不是“更棘手”,请阅读我的答案,方法就在那里。你似乎精通机器人框架,我想你会得到一个简单的拆分和连接操作来工作。我以前没有使用过它,所以我不能那么容易地做到。
    • 它“更棘手”,因为 a) 我会采用不同的方法,不是在 xpath 中连接,而是使用contains(text(), 'split_part') 扩展条件集,b) 逻辑应该适应案例没有引号的地方,因此 py 的 '"'.join(result_set) 上的 1 成员结果数组不会返回被包围的字符串,c) 这需要编写更多的代码行,d) 我不愿意在手机的键盘上这样做,除非 e) @op 真正需要 f) 并且需要帮助来实现。所以“很多”是合适的形容词 IMO ;)
    • @Todor:谢谢!双引号在我的情况下有效。
    【解决方案3】:

    我没有测试过,但你可以试试:

    //ul[@id='xyz-ul']/li[contains(text(),'Épargne en vue d'un objectif précis')]
    

    【讨论】:

    • 不,XPath 中没有转义序列,尤其是 XML 转义序列。此外,即使在 XML/XSLT 中,这仍然是无效的。
    • 那么这将起作用(至少在这种情况下): //ul[@id='xyz-ul']/li[starts-with(text(),'Épargne en vue d' ) 和结尾(text(),'un objectif précis')]
    • 这可行,但对于事先不知道输入字符串的测试框架来说,这是完全不可行的。而且它会匹配误报,因为它允许介于两者之间的任何东西,所以这种方法是有缺陷的。
    • 我期待得到这样的回应。为了在所有场景中使用此方法,OP 需要编写一个函数来计算单个撇号并相应地手动构建 xpath 字符串。我并不是说这很简单,但它是可行的。有时你有两个选择:一个艰难的解决方案或没有解决方案。
    • @Tomalak 我必须纠正你的这些陈述——“对于你事先不知道输入字符串的测试框架来说是不可行的”。 robotsframework 有非常好的字符串处理能力,事实上——python 中的一切都在这里适用。
    猜你喜欢
    • 2019-03-16
    • 2013-11-20
    • 2016-01-06
    • 1970-01-01
    • 2019-10-09
    • 1970-01-01
    • 2021-01-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多