0

org.jdom2.xpath用来评估对文档的XPath查询。html尝试从head元素中检索脚本文本,我尝试了以下查询:

/html/head/script[contains(text(), 'expression1') and contains(text(), 'expression2')]/text()

此查询在XPath HelperChrome 控制台($x查询)中返回单个结果,但使用org.jdom2.xpath.

尝试更简单(但更重)的查询:

//script[contains(text(), 'expression1') and contains(text(), 'expression2')]/text()

产生相同的结果。

代码示例:

String xpath = "/html/head/script[contains(text(), 'expression1') and contains(text(), 'expression2')]/text()";
List<Text> tokeScriptResults = (List<Text>) xpathFactory.compile(xpath).evaluate(document);

事后思考:查看Document对象,我发现由于脚本文本很长,jdom2因此将其拆分为Texts 数组而不是一个 long Text。这可能是问题吗?

4

1 回答 1

2

简短的回答 - 使用.而不是text(),即contains(., 'expression1')

更长的答案 -text()是一个路径步骤,它选择作为上下文节点的直接子节点的所有文本节点的集合。contains函数期望它的参数是字符串,而不是节点集,并且在 XPath 1.0 中将节点集转换为字符串的规则是按文档顺序获取集合中第一个节点的字符串值并完全忽略其他节点。因此,测试contains(text(), 'expression1')只查看第一个文本节点子节点。

相反,如果您这样做,contains(., 'expression1')则第一个参数是包含单个节点(脚本元素)的集合,元素节点的字符串值是其所有后代文本节点按文档顺序的串联。所以这将查看 script 标签下的所有文本,而不仅仅是第一个文本节点子节点。

一般来说,您应该很少需要text()在 XPath中使用。仅当您绝对必须单独处理每个单独的文本节点时才需要它。在谓词中,我发现测试元素节点的字符串值几乎总是能更好地捕捉意图。

于 2014-08-08T08:16:05.697 回答