小编典典

与具有多个文本子节点的节点一起使用时,XPath contains(text(),'some string') 不起作用

all

我对 dom4j 包含的 XPath 有一个小问题…

假设我的 XML 是

<Home>
    <Addr>
        <Street>ABC</Street>
        <Number>5</Number>
        <Comment>BLAH BLAH BLAH <br/><br/>ABC</Comment>
    </Addr>
</Home>

假设我想在给定根元素的文本中找到所有具有 ABC 的节点…

所以我需要编写的 XPath 是

//*[contains(text(),'ABC')]

然而,这不是 dom4j 返回的......这是一个 dom4j 问题还是我理解 XPath
的工作原理,因为该查询只返回Street元素而不返回Comment元素?

DOM 使Comment元素成为具有四个标签的复合元素

[Text = 'XYZ'][BR][BR][Text = 'ABC']

我会假设查询应该仍然返回元素,因为它应该找到元素并在其上运行包含,但它没有......

以下查询返回元素,但它返回的远不止元素——它还返回父元素,这对问题来说是不可取的。

//*[contains(text(),'ABC')]

有谁知道只返回元素<Street/>和的 XPath 查询<Comment/>


阅读 117

收藏
2022-04-08

共1个答案

小编典典

<Comment>标记包含两个文本节点和两个<br>作为子节点的节点。

你的 xpath 表达式是

//*[contains(text(),'ABC')]

为了打破这一点,

  1. *是一个匹配任何元素(即标签)的选择器——它返回一个节点集。
  2. []是在该节点集中的每个单独节点上运行的条件。如果它操作的任何单个节点与括号内的条件匹配,则它匹配。
  3. text()是一个匹配所有作为上下文节点子节点的文本节点的 选择器——它返回一个节点集。
  4. contains是一个对字符串进行操作的函数。如果传递一个节点集,则通过返回节点集中在文档顺序中排在第一位的节点的字符串值,将节点集转换为字符串。因此,它只能匹配<Comment>元素中的第一个文本节点——即BLAH BLAH BLAH. 由于这不匹配,因此您不会<Comment>在结果中得到 a。

您需要将其更改为

//*[text()[contains(.,'ABC')]]
  1. *是一个匹配任何元素(即标签)的选择器——它返回一个节点集。
  2. 外部[]是在该节点集中的每个单独节点上操作的条件 - 这里它在文档中的每个元素上操作。
  3. text()是一个匹配所有作为上下文节点子节点的文本节点的 选择器——它返回一个节点集。
  4. 内部[]是在该节点集中的每个节点上操作的条件 - 这里是每个单独的文本节点。每个单独的文本节点都是括号中任何路径的起点,也可以.在括号内明确引用。如果它操作的任何单个节点与括号内的条件匹配,则它匹配。
  5. contains是一个对字符串进行操作的函数。这里传递了一个单独的文本节点 ( .)。由于它单独传递<Comment>标签中的第二个文本节点,因此它将看到'ABC'字符串并能够匹配它。
2022-04-08