XPath:获取两个空节点之间的所有内容

时间:2018-05-23 09:24:51

标签: xml xpath xquery

我需要编写一个xpath expr来获取空节点( pb )和下一次 pb 之间的所有内容(节点和文本)。

我可以得到"一切"在 pb 节点之后,直到带有此查询的XML文件结束:

 //pb/following::*|//pb/following::text()

但我想将"单身" pb到下一个pb的结果。

示例:

...
<pb/>
<elementX>text here </elementX>     --|
<moreElements/>                       |    Group 1
Plain text here without element     --|
<pb/>
<elementY>text here </elementY>     --|    Group 2
...                                 --|
<pb/>
...                                 --|    Group 3
EOF                                 --|

所以我想要2 pb 之间的所有内容并将其分组。对于此示例,应该有3个结果组。第一个 pb 直到第二个的所有元素都应该在第一组中。从第二个 pb 到第三个 pb 是第二个组。从第三个 pb 到最后应该有第三组。

难以用语言描述。需要进一步的信息?

如何告诉xpath在哪里结束并对结果进行分组?

提前谢谢。

2 个答案:

答案 0 :(得分:1)

如果要创建组,XPath将不够(因为结果将始终是一个平坦的序列)。 XQuery 1.0解决方案如下所示:

for $pb in //pb
let $next-pb := $pb/following-sibling::pb[1]
return element group {
  $pb/following-sibling::node()[empty($next-pb) or . << $next-pb]
}

如果您的处理器支持XQuery 3.0,您可以使用更有效的窗口子句:

declare context item := document {
  <xml>
    <pb/>
    <elementX>text here </elementX>
    <moreElements/>
    Plain text here without element
    <pb/>
    <elementY>text here </elementY>
    ...
    <pb/>
    x
  </xml>
};
for tumbling window $w in /xml/node()
    start $s when name($s) = 'pb'
    end $e when name(head($e/following-sibling::node())) = 'pb'
return element group { tail($w) }

答案 1 :(得分:1)

正如Christian指出的那样,XPath只能提供节点集(或节点序列),因此无法进行任何分组。在两个里程碑标记<start/><end/>之间传递节点也很棘手(但并非不可能)。在XPath 1.0中,您可以这样做:

start/following-sibling::node()[following-sibling::end]

但使用长输入序列可能效率很低。使用XQuery窗口或XSLT分组的解决方案更令人满意。