为什么normalize-space(text())无法与前面的子元素一起使用?

时间:2019-04-15 13:56:09

标签: html xpath

毫无疑问,这是非常基础的,但是尽管我到目前为止已经进行了研究,但它不会为我“点击”。给出以下两个HTML示例:

示例1

<div _ngcontent-c35="" class="row facet-container ng-star-inserted">
    <div _ngcontent-c35="" class="searchresult-header">
        Locatie
    </div>
</div>

示例2

<div _ngcontent-c42="" class="row facet-panel ng-star-inserted">
    <div _ngcontent-c42="" class="facet-panel-header brand-pointer" data-target="#ft5" data-toggle="collapse">
        <span _ngcontent-c42="" class="icon-plus ng-star-inserted" data-target="#ft5" data-toggle="collapse">
        </span> 
        Locatie
    </div>
    <div _ngcontent-c42="" class="collapse" id="ft5">
    </div>
</div>

现在我有以下xpath:

// div [.// div [normalize-space(text())='Locatie']]

根据其他questions和有关xpath的网站,text()会选择文本节点,这些文本节点直接位于我们正在搜索的节点上。因此,在示例1中,我希望检索第一个子“ div”元素。这可以正确发生:那里没有问题。

我希望在示例2中得到相同的结果。但是,事实并非如此:显然,“ span”元素会干扰此特定搜索。当我手动删除它时,我成功检索到所需的“ div”元素。为什么搜索中断?文本应该仍然是div元素的直接子元素,无论span元素是否存在。

TLDR:为什么“ span”元素使我无法在示例2中找到第二个“ div”元素?

3 个答案:

答案 0 :(得分:2)

我想那是因为normalize-space(text())='Locatie']打算检查 first 子文本节点(实际上只是一个空字符串),而您需要检查 second 一个:

//div[.//div[normalize-space(text()[2])='Locatie']]

如果您需要适用于两种情况的通用XPath,请尝试

//div[normalize-space(div)='Locatie']

答案 1 :(得分:2)

Jason had answered一样,这是因为normalize-space()函数的签名符合规范:

  

功能字符串 规范化空间字符串?)

在XPath 1.0中,每当需要字符串参数时,该语言就会通过string()函数来应用类型转换。根据规格:

  

通过返回的字符串值将节点集转换为字符串   节点集中按文档顺序排在第一位的节点。如果   节点集为空,返回空字符串。

因此,从text()节点测试得到的节点集被缩减为文档顺序中的第一个节点,然后将该节点转换为其string-value。 / p>

在这方面,当总是监督空白时,只有文本节点会引起注意:您的div元素有两个文本节点:

<div>
    <div>
        <!-- HERE ENDS THE FIRST --><span>
        </span> 
        Locatie
    <!-- HERE ENDS THE SECOND --></div>
    <div>
    </div>
</div>

每当您混合使用内容标记时,最好使用字符串值而不是文本节点。否则,您应该使用以下表达式:

//div[.//div/text()[normalize-space()='Locatie']]

答案 2 :(得分:0)

这可能与白色文本/空格有关(这超出了我的薪资等级...),因为随着焦点的改变,以下表达式似乎适用于大多数(并非全部)xpath测试人员:

.//div[text()[contains(.,'Locat')]]