我正在尝试在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>
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>
产量
<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>
输出正确排序;首先是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>
产量
<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>
如您所见,它首先在b上进行排序(降序).这是因为这是顺序中if语句的顺序;不是变量序列的顺序($orderby).如果我交换ifs的顺序(首先测试c),它排序很好.
我也有这个工作在eXist,但它不处理下降:
order by util:eval(concat('$foo/',string-join(tokenize($orderby,'\s')[1],',$foo/')))