假设输入 XML 在文件中,则in.xml
此 XQuery 脚本会执行您想要的操作:
(:
This library function can be found here:
http://www.xqueryfunctions.com/xq/functx_index-of-node.html
:)
declare namespace functx = "http://www.functx.com";
declare function functx:index-of-node($nodes as node()* ,
$nodeToFind as node() ) as xs:integer*
{
for $seq in (1 to count($nodes))
return $seq[$nodes[$seq] is $nodeToFind]
};
(:
Recursively calculate the start elements with the other elements between
as childs.
Take the first two indices of $positions and create a start element
with the elements of $elements with positions between these two indices.
Then remove the first index of $position and do the recursive call.
Input:
$positions: Sequence with start element indices (belongs to $elements)
$elements: Element sequence
Output:
Sequence of start elements with child elements
:)
declare function local:partition($positions as xs:integer*,
$elements as element()*) as element()*
{
let $len := count($positions)
return
if($len gt 1)
then (
let $first := $positions[1]
let $second := $positions[2]
let $rest := subsequence($positions, 2)
return
( element start
{
subsequence($elements, $first + 1, $second - $first - 1)
},
local:partition($rest, $elements)
)
)
else if($len eq 1)
then (
element start
{
subsequence($elements, $positions[1] + 1)
}
)
else ()
};
(: Input document :)
let $input-doc := doc('in.xml')
(: Sequence of all child elements of root element doc :)
let $childs := $input-doc/doc/node()[. instance of element()]
(: Sequence with the indices of the start elements in $childs :)
let $positions := for $s in $input-doc/doc/start
return functx:index-of-node($childs, $s)
return
<doc>
{
local:partition($positions, $childs)
}
</doc>
输出是:
<doc>
<start>
<a/>
<b/>
<item/>
<item/>
<item/>
</start>
<start>
<item/>
<item/>
<item/>
</start>
<start>
<b/>
<item/>
<item/>
<item/>
</start>
</doc>
使用 XQilla 的Testet但每个其他 XQuery 处理器都应该产生相同的结果。