【问题标题】:How can I find the exact value using xpath in selenium webdriver for text that contains  ?如何在 selenium webdriver 中使用 xpath 找到包含的文本的确切值?
【发布时间】:2019-03-26 11:13:48
【问题描述】:

我在使用 xpath 从代码中选择确切的文本“部分”时遇到问题。

** 需要明确的是,如果可能的话,我需要从元素的 innerText 或 innerHTML 中进行准确的文本选择,而不是 id。 **

我可以使用包含文本功能,但这会导致包含“Section”的其他部分匹配也被返回/突出显示:


//div[@aria-hidden='false']//ul/li[contains(text(),'Section')]

我尝试过使用以下方法,但我不知道我的语法是否正确,因为没有返回/突出显示:


//div[@aria-hidden='false']//ul/li[text()='Section')]

//div[@aria-hidden='false']//ul/li[.='Section']

//div[@aria-hidden='false']//ul/li[normalize-space(.)='Section']

这是检查 Section 节点时显示的内容:


<li id="GOS--/40" class="nodecollapsed item parent-node xh-highlight" style="" xpath="1">
                                Section&nbsp;<span class="child-count"></span>
                            </li>

这是元素属性中显示的内容:


id: "GOS--/40"
innerHTML: "↵                                Section&nbsp;<span class="child-count"></span>↵                            "
innerText: " Section "

这是显示返回的其他部分匹配的 xml:

<div class="selection-list-dialog modal-dialog Dialog">
    <div class="modal-content">
        <div class="modal-header SectionHeader">
            <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
            <span class="modal-title" data-lang="StandardItems">Standard Items</span>
        </div>
        <div class="modal-body selection-list-container" style="margin-top: 30px" id="base">
            <div>
                <span data-lang="SelectItemInstructions">Select the items you are interested in from the list.</span>
            </div>
            <br/>
            <div class="pull-left selection-tree-container">
                <h4 class="selection-list-title">
                    <span data-lang="Available">Available</span>                    
                </h4>
                <ul class="selection-list selection-tree-list">



                            <li id="CS--/14" class="nodecollapsed item parent-node">
                                Country Section&nbsp;<span class="child-count"></span>
                            </li>                        


                            <li id="Sec1--/23" class="nodecollapsed item parent-node">
                                Section 1&nbsp;<span class="child-count"></span>
                            </li>


                            <li id="Sec2--/24" class="nodecollapsed item parent-node">
                                Section 2&nbsp;<span class="child-count"></span>
                            </li>


                            <li id="GOS--/40" class="nodecollapsed item parent-node">
                                Section&nbsp;<span class="child-count"></span>
                            </li>


                            <li id="RS--/43" class="nodecollapsed item parent-node">
                                Regional Section&nbsp;<span class="child-count"></span>
                            </li>

【问题讨论】:

  • 由于值文本的格式很重,您可以使用 starts-with 或 contains xpath 属性。
  • 选择确切的文本'Section'是什么意思?您是否尝试提取文本 Section
  • 我已经在使用 contains 并返回多个选项,这就是问题所在。从我不确定如何在上面使用开始,它什么也没返回。你能举个例子吗?
  • @DebanjanB 我需要精确的文本,因为在使用包含功能时还有其他部分匹配,而我需要精确匹配才能单击它。我在我的问题中添加了一些进一步的信息
  • @JackFleeting 不幸的是,它并不总是相同的必需项,或者我可以将其硬编码并使用 id。我是一名测试人员,我们通过 csv 将数据传递到 Selenium Webdriver。随着后台数据的定期更新,这些数据可能会发生变化,并且我们有不同版本的数据可以通过网站传递。我们将其用作测试数据是否按预期提取的自动化方式,并通过输入选择来生成报告,从而使用数据自动生成报告。

标签: selenium xpath exact-match non-breaking-characters


【解决方案1】:

这是一个艰难的过程。问题是您有许多类似的选项都包含某种风格的“部分”,并且很难将它们区分开来。除此之外,每个都包含一个不间断的空格&amp;nbsp;,这意味着normalize-space() 也不会(直接)工作。

但是...我发现下面的 XPath 可以工作。

//li[normalize-space()='Section\u00a0']

normalize-space() 删除空格(但不是&amp;nbsp),因此您必须使用\u00a0 将其添加到其中。我已经在本地对此进行了测试,并且可以正常工作。

【讨论】:

  • 很遗憾这不起作用,但感谢您的全面回答
  • normalize-space() 将去除“S XML 生产允许的前导和尾随空格”:S ::= (#x20 | #x9 | #xD | #xA)+
  • 我正在使用 XPath Helper 来检查 xpath 并使用了我原始 xpath 的一部分://div[@aria-hidden='false']//ul//li[normalize-space()='Section\u00a0'] 它返回了 [NULL] 的结果我认为我不能发布指向该页面的链接出于安全原因
  • @JeffC 抱歉,我按照您发布的方式和原始 xpath 的一部分尝试了两种方法,但均未返回结果
  • @JeffC normalize-space 不应在结尾留下#xA。此外,实体引用会在信息集中展开,除非解析器未进行验证。在这种情况下,它可能会留下一个unexpanded entity reference
【解决方案2】:

尝试关注xpath 看看是否有帮助。

 //li[starts-with(@id,'GOS')][@class='nodecollapsed item parent-node xh-highlight']

  //li[@class='nodecollapsed item parent-node xh-highlight'][@xpath='1']

【讨论】:

  • 如果我稍微编辑一下,上面的那个就可以了,但是它使用的是 id 'GOS' 而不是所需元素的文本 'Section'。 //div[@aria-hidden='false']//ul//li[starts-with(@id,'GOS')] 但是我需要使用文本,因为它是显示在前端的内容,它用于输入数据以进行测试,具体取决于当时使用的数据版本。我将编辑我的问题以包含元素属性以获取更多信息。
  • @Redflame:你试过了吗://div[@aria-hidden='false']//ul//li[contains(text(),'Section')]
  • 是的,这就是我目前在我的问题中使用的内容。但是我不想使用它,因为它返回部分匹配而不是完全匹配。
  • @Redflame : 你的更新不清楚。你能发布新的 html 吗?
  • 不确定你的确切意思,但要清楚,如果可能的话,我需要从元素的 innerText 或 innerHTML 中进行确切的文本选择,而不是 id。我已经在使用包含,但这会导致返回部分匹配,例如而不仅仅是“Section”,我会得到“Section”、“Country Section”、“Section 1”等
【解决方案3】:

您可以尝试下面的 XPath 来查找节节点

试试看有没有用

//li[@id='GOS--/40'][contains(text(),'Section')]

【讨论】:

  • 我在我的问题中添加了更多信息,因为我不能使用元素的 id
【解决方案4】:

让我把帽子扔进擂台......

//li[(normalize-space(text()) = 'Section')]

【讨论】:

  • 不幸的是这不起作用,我不知道您是否看到上面 JeffC 的答案,但认为它可能与不间断空格的问题有关  
  • @Redflame - 我做到了;奇怪的是他的建议(//li[normalize-space()='Section\u00a0'])对我也不起作用;但//li[normalize-space((text())='Section'] 可以。无法解释。
  • 似乎都不适合我,所以我会继续努力。感谢您的建议
  • @Redflame - 不用担心;这是我很长一段时间以来最有趣的:D;忘记标准化文本 - 试试这个 //div/ul/li[text()=' Section '] 并告诉我。
  • 至少你玩得开心!恐怕这也没有用
【解决方案5】:

这是仅从父级获取文本的方法。 (排除child(ren)中的文字)

在 Python 中:

def get_pure_element_text(element):
    return driver.execute_script(
        """
        var parent = arguments[0];
        var child = parent.firstChild;
        var textValue = "";
        while(child) {
            if (child.nodeType === Node.TEXT_NODE)
                    textValue += child.textContent;
                    child = child.nextSibling;
        }
        return textValue;""",
        element).strip()

此方法将迭代所有 firstChild(直接子级)并从所有文本节点中提取所有文本。

在这种情况下如果要检索 li 的 id 为 GOS--/40 的文本,请使用以下方法。

element = driver.find_element_by_xpath("//li[@id='GOS--/40']")
print(get_pure_element_text(element))   

分享这个方法,至少可以帮助其他人(如果不是这个上下文中的 OP)。

C# 实现:(未测试)

string get_pure_text(IWebDriver driver, IWebElement element){
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
    return (string)js.ExecuteScript(""""
        var parent = arguments[0];
        var child = parent.firstChild;
        var textValue = "";
        while(child) {
            if (child.nodeType === Node.TEXT_NODE)
                    textValue += child.textContent;
                    child = child.nextSibling;
        }
        return textValue;""",
        element");

用法:

string output = get_pure_text(driver,element)

【讨论】:

  • 谢谢@supputuri c# 的代码是否类似?
  • 包括 c# 实现,让我知道它是怎么回事。我没有检查方法,因为我的机器上没有 C# 环境。
猜你喜欢
  • 2012-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-12
  • 1970-01-01
  • 1970-01-01
  • 2018-01-03
  • 2012-06-04
相关资源
最近更新 更多