在节点内容文本上查找父节点

时间:2011-02-01 10:48:29

标签: php xpath

嘿,我正在尝试找出节点内容文本的父节点。

示例:

<div>
    <h1>Node to find</h1>
    <p>another node</p>
</div>

我的所有代码都知道节点中的文本是什么,我的脚本需要找出文本包含的节点。

我尝试过以下xpath:

 1. //*[. = "'. $text .'"]
 2. //*[contains(., "'. $text .'")]

第一个给我一个空的nodeList 第二个给了我很多节点,但它给了我所有包含文本的父节点,我只想要第一个节点。

感谢您的帮助。

2 个答案:

答案 0 :(得分:3)

我不确定我理解你的答案的"'. $text .'"部分...我想这意味着一些示例文本,而不是对名为text的变量的预期引用?

无论如何,当你使用contains(., "foo")时,你会问当前节点的字符串值是否包含“foo”。当前节点的字符串值是所有后代文本节点的字符串值的串联。这就是//*[contains(., "foo")]返回节点列表的原因:它匹配包含“foo”的每个文本节点的每个祖先。 (并且它可能非常低效,因为您正在树中的每个节点上执行该连接功能。)

你的starts-with()答案工作(有时)的原因是你很幸运:文本节点的父节点有其他前面的兄弟节点有自己的文本,所以祖父节点的文本值以其他东西开始。效率也非常低......

如果您要查找的文本只在一个文本节点中 - 即它不会被分割为多个元素/注释等 - 那么您可以高效准确地匹配包含文本的元素节点,使用 [已编辑]

//*[text()[contains(., "foo")]]

(类似于@biziclop所说的)。

如果您正在寻找的文字可能会被拆分为多个元素/评论/等等 - 那么您可以使用 [已编辑,两次]

//*[contains(., "foo") and not(*[contains(., "foo")])]

但那效率很低。以下不保证可以正常工作:

//*[contains(., "foo")][1]

它将为您提供 [已编辑,两次] 每个元素,它是其父级的第一个子级(是其中一个的祖先)包含文本。 (或者是一个空的节点集,如果找不到“foo”。)我相信@Alejandro就此...我还没有内化如何判断[position()= x]何时适用于最近的位置步骤只要。无论如何,这个XPath表达式无法保证为您提供正确的结果。

答案 1 :(得分:1)

  

我正试图找出父节点   节点内容文本。
  [...]但它给了我所有的父母   包含文本,我只想要   第一个父母。

经典的答案是:

//*[text()[contains(.,$pText)]]

含义:具有至少一个文本节点子元素的任何元素包含$pText变量/参数字符串值作为其字符串值的一部分

有人提到了混合内容模型。我怀疑这是一个真正的考虑,但无论如何,这是答案:

//*[contains(.,$pText)][not(*[contains(.,$pText)])]

含义:任何包含$pText的元素作为其字符串值的一部分,没有任何子元素$pText作为其字符串值的一部分。换句话说,最里面的元素包含$pText字符串值。