如果您有任何想法如何改进问题,我将尽力解释我的问题和预期结果。
假设我有一个.xml文档,如下所示;
的test.xml
<db>
<www>
<year >1990</year>
<author>Daren</author>
</www>
<www>
<year>1990</year>
<author>Daren</author>
</www>
<www>
<year>1989</year>
<author>Daren</author>
</www>
</db>
db是root用户,www是root的孩子,而另一些孩子则是www。
我想按年份对记录进行分组;我已设法使用以下代码执行此操作:
<publications>
{
for $x in distinct-values(/*/*/year)
let $item := /*/*[year = $x]
where $item/author = "Daren"
return <year-Pub>{<year>{$x}</year>} {for $i in $item where $i/author = "Daren" return $i }</year-Pub>
}
</publications>
其输出为:
<?xml version="1.0" encoding="UTF-8"?>
<publications>
<year-Pub>
<year>1990</year>
<www>
<year>1990</year>
<author>Daren</author>
</www>
<www>
<year>1990</year>
<author>Daren</author>
</www>
</year-Pub>
<year-Pub>
<year>1989</year>
<www>
<year>1989</year>
<author>Daren</author>
</www>
</year-Pub>
</publications>
Harray!这就是我希望按年份分组的记录完整无缺。然后,我想从每个单独的记录中删除<year></year>
标记,因为它显示在分组记录的顶部。这就是问题依然存在的地方。我设计了一种方法,使用$i/*[not(name()="year")]
从每个条目中删除记录标记
像这样:
<publications>
{
for $x in distinct-values(/*/*/year)
let $item := /*/*[year = $x]
where $item/author = "Daren"
return <year-Pub>{<year>{$x}</year>} {for $i in $item where $i/author = "Daren" return $i/*[not(name()="year")] }</year-Pub>
}
</publications>
但输出是:
<?xml version="1.0" encoding="UTF-8"?>
<publications>
<year-Pub>
<year>1990</year>
<author>Daren</author>
<author>Daren</author>
</year-Pub>
<year-Pub>
<year>1989</year>
<author>Daren</author>
</year-Pub>
</publications>
正如您所看到的<www></www>
标签消失了,我可以看到为什么这是因为当您写$i/*[not(name()="year")]
时,您要说的是从$i
开始下一步www的子项并返回没有<year></year>
标记的记录。我只是不确定如何修改我的代码以提供所需的结果,其中包含<www></www>
标记并删除了<year></year>
标记。
答案 0 :(得分:1)
使用XQuery 3.0,您可以使用group by
表达式对结果进行分组。然后我还为你编写了一个过滤函数,它将删除特定名称的任何后代元素。您可以使用该过滤器功能过滤出year
www
以及您希望的任何其他元素。
xquery version "3.0";
declare function local:filter($nodes as node()*, $names as xs:string+) {
for $n in $nodes
return
typeswitch($n)
case element() return
if(not(local-name($n) = $names))then
element {node-name($n)} {
local:filter($n/(@*|child::node()), $names)
}
else()
default return
$n
};
<publications>
{
for $w in /db/www
let $year := $w/year
group by $year
return
<year-Pub>
<year>{$year}</year>
{
(: add any other names you wish to
filter into the sequence with "year" :)
local:filter($w, ("year"))
}
</year-Pub>
}</publications>
答案 1 :(得分:0)
然后你可以在<www>
:
$i/*[not(name()="year")]
<publications>
{
for $x in distinct-values(/*/*/year)
let $item := /*/*[year = $x]
where $item/author = "Daren"
return
<year-Pub>
{<year>{$x}</year>}
{
for $i in $item
where $i/author = "Daren"
return <www>{$i/*[not(name()="year")]}</www>
}
</year-Pub>
}
</publications>
输出:
<?xml version="1.0" encoding="UTF-8"?>
<publications>
<year-Pub>
<year>1990</year>
<www>
<author>Daren</author>
</www>
<www>
<author>Daren</author>
</www>
</year-Pub>
<year-Pub>
<year>1989</year>
<www>
<author>Daren</author>
</www>
</year-Pub>
</publications>