Dan*_*ley 5 xml sorting xquery marklogic exist-db
我正在尝试在XQuery中实现动态排序.我目前正在使用Saxon-PE 9.5进行开发,但是将在eXist和marklogic中使用XQuery(或xqueries复数),因此使用其模块/函数的任何答案都可以(并且希望其他数据库具有相应的模块/函数) .
排序基于包含一系列字符串的变量.序列中的每个字符串都是元素的名称和可选的"降序".
我已经尝试了多种方法,但无法按照预期的方式工作; 特别是对于二级种类.
在下面的示例中,排序是静态的,并且具有主要类型c(升序)和次要类型b(降序)...
so_xquery_question.xml
<doc>
<foo id="foo1">
<a>a1</a>
<b>b1</b>
<c>c0</c>
</foo>
<foo id="foo2">
<a>a2</a>
<b>b2</b>
<c>c0</c>
</foo>
<foo id="foo3">
<a>a3</a>
<b>b3</b>
<c>c3</c>
</foo>
</doc>
Run Code Online (Sandbox Code Playgroud)
XQuery的
let $xml := doc('file:///C:/SO/so_xquery_question.xml')
return
<test>{
for $foo in $xml/doc/foo
order by $foo/c, $foo/b descending
return
$foo
}</test>
Run Code Online (Sandbox Code Playgroud)
产量
<test>
<foo id="foo2">
<a>a2</a>
<b>b2</b>
<c>c0</c>
</foo>
<foo id="foo1">
<a>a1</a>
<b>b1</b>
<c>c0</c>
</foo>
<foo id="foo3">
<a>a3</a>
<b>b3</b>
<c>c3</c>
</foo>
</test>
Run Code Online (Sandbox Code Playgroud)
输出正确排序; 首先是c(升序)然后是b(降序).
我的最新尝试部分有效.(在Saxon和marklogic中.由于某些未知原因(!@#$),它在eXist中的工作方式不同.)
这里是:
XQuery的
let $orderby := ('c','b descending')
let $xml := doc('file:///C:/SO/so_xquery_question.xml')
return
<test>{
for $foo in $xml/doc/foo
order by
if ($orderby='b') then $foo/b else (),
if ($orderby='b descending') then $foo/b else () descending,
if ($orderby='c') then $foo/c else (),
if ($orderby='c descending') then $foo/c else () descending
return
$foo
}</test>
Run Code Online (Sandbox Code Playgroud)
产量
<test>
<foo id="foo3">
<a>a3</a>
<b>b3</b>
<c>c3</c>
</foo>
<foo id="foo2">
<a>a2</a>
<b>b2</b>
<c>c0</c>
</foo>
<foo id="foo1">
<a>a1</a>
<b>b1</b>
<c>c0</c>
</foo>
</test>
Run Code Online (Sandbox Code Playgroud)
如您所见,它首先排序b(降序).这是因为那是if语句中的顺序order by; 不是变量序列($orderby)的顺序.如果我交换ifs 的顺序(c第一次测试),它排序很好.
我也有这个在eXist工作,但它没有处理descending:
order by util:eval(concat('$foo/',string-join(tokenize($orderby,'\s')[1],', $foo/')))
Run Code Online (Sandbox Code Playgroud)
我有什么方法可以进行动态排序,并考虑以下因素?
在尝试实施@mblakele的建议时,我确实让它发挥作用......
X查询
let $orderby := ('c','b descending')
let $xml := doc('file:///C:/SO/so_xquery_question.xml')
return
<test>{
for $foo in $xml/doc/foo
order by
if ($orderby[1]='b') then $foo/b else (),
if ($orderby[1]='b descending') then $foo/b else () descending,
if ($orderby[1]='c') then $foo/c else (),
if ($orderby[1]='c descending') then $foo/c else () descending,
if ($orderby[2]='b') then $foo/b else (),
if ($orderby[2]='b descending') then $foo/b else () descending,
if ($orderby[2]='c') then $foo/c else (),
if ($orderby[2]='c descending') then $foo/c else () descending
return
$foo
}</test>
Run Code Online (Sandbox Code Playgroud)
输出
<test>
<foo id="foo2">
<a>a2</a>
<b>b2</b>
<c>c0</c>
</foo>
<foo id="foo1">
<a>a1</a>
<b>b1</b>
<c>c0</c>
</foo>
<foo id="foo3">
<a>a3</a>
<b>b3</b>
<c>c3</c>
</foo>
</test>
Run Code Online (Sandbox Code Playgroud)
我正在做的是检查序列中的第一项是否有可能的值,然后检查序列中的第二项。这将确保维持序列的顺序。
优点:
缺点:
if语句!!)来说会很难看。