考虑父标签和子标签,我会计算所有不同的项目。
例如,如果文档包含:
<root>
<A value="5.1">
<B value="3.5">
<C value="1.4">
<D value="0.2">
<E value="X"/>
</D>
</C>
</B>
</A>
<A value="5.1">
<B value="3.5">
<C value="1.4">
<D value="0.4">
<E value="Y"/>
</D>
</C>
</B>
</A>
<A value="4.6">
<B value="3.1">
<C value="1.5">
<D value="0.2">
<E value="X"/>
</D>
</C>
</B>
</A>
<A value="5.0">
<B value="3.6">
<C value="1.4">
<D value="0.2">
<E value="X"/>
</D>
</C>
</B>
</A>
</root>
我将计算AB,ABC,ABCD,BCD等所有不同的项目。
我尝试了这个xquery命令,但是仅获得了单个项目的不同值:
count(distinct-values(doc('partitioncollection')/root/A/@value)) -> 3
count(distinct-values(doc('partitioncollection')/root/B/@value)) -> 3
count(distinct-values(doc('partitioncollection')/root/C/@value)) -> 2
更具体地说,如果我想计算所有可能值对的计数,结果应显示:
A/B : 3
A/B/C : 3
A/B/C/D : 4
A/B/C/D/E : 4
B/C : 3
B/C/D : 4
B/C/D/E : 4
C/D : 3
C/D/E : 3
D/E : 2
C/E : should be 3 because there are 3 distinct pairs of values:
<C value="1.4"><E value="X"/>
<C value="1.4"><E value="Y"/>
<C value="1.5"><E value="X"/>
A/D : should be 4 because there are 4 distinct pairs of values:
<A value="5.1"><D value="0.2">
<A value="5.1"><D value="0.4">
<A value="4.6"><D value="0.2">
<A value="5.0"><D value="0.2">
etc.
由于计算复杂,我相信创建一个以单个标记集(即A-D或C-E等)并返回计数器值的函数会更容易
答案 0 :(得分:2)
我仍然不确定问题的描述是否准确(不清楚结构是否始终为A/B/C/D/E
,也不清楚对于更深层次的内容是否只想比较,例如B/C
是具有相同值的A
的子代),但总的来说,我认为可以使用分组和递归来解决;我想出了
declare function local:distinct-descendants($elements as element()*) as xs:string*
{
for $element-group in $elements[*]
group by $element-name := node-name($element-group)
let $max-depth := max($element-group/count(.//*)) + 1
for $level in 2 to $max-depth
let $groups :=
for $path-group in $element-group
group by $group-path := string-join(subsequence($path-group/descendant-or-self::*/node-name(), 1, $level), '/')
for $value-group in $path-group
group by $value-seq := string-join(subsequence($value-group/descendant-or-self::*/@value, 1, $level), '|')
return head($group-path)
for $level-group in $groups
group by $level-path := $level-group
order by head($level)
return $level-path || ' : ' || count($level-group)
,
if ($elements/*) then local:distinct-descendants($elements/*) else ()
};
local:distinct-descendants(root/*)
在https://xqueryfiddle.liberty-development.net/nbUY4kz/4,此输出
A/B : 3
A/B/C : 3
A/B/C/D : 4
A/B/C/D/E : 4
B/C : 3
B/C/D : 4
B/C/D/E : 4
C/D : 3
C/D/E : 3
D/E : 2
使用BaseX可以得到相同的结果。
如果结构始终为A/B/C/D/E
,则代码可能有点太复杂,在这种情况下,不需要node-name()
上的第一个分组。
我还必须在“路径”序列(例如A/B/C
)和@value
序列上分组两次,也许有更简单的方法,但是我无法关联唯一的{ {1}}具有嵌套结构的序列,无需进行重复的分组。
也许
@value
在https://xqueryfiddle.liberty-development.net/nbUY4kz/6的有点简单,但仍然可以完成工作。
我认为,只要子树都有一个孩子,但是前两次尝试都可以,但是如果没有,则尝试失败。因此,在子元素数量任意的一般情况下,似乎有必要计算后代的路径和值并将其分组:
declare function local:distinct-descendants($elements as element()*) as xs:string*
{
let $max-depth := max($elements/count(descendant-or-self::*))
for $level in 2 to $max-depth
let $groups :=
for $path-group in $elements
group by
$group-path := string-join(subsequence($path-group/descendant-or-self::*/node-name(), 1, $level), '/'),
$value-seq := string-join(subsequence($path-group/descendant-or-self::*/@value, 1, $level), '|')
return head($group-path)
for $level-group in $groups
group by $level-path := $level-group
order by head($level)
return $level-path || ' : ' || count($level-group)
,
if ($elements/*) then local:distinct-descendants($elements/*) else ()
};
local:distinct-descendants(root/*)