我正在尝试在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/')))
这是XQuery 1.0中的一个漏洞,我认为3.0没有修复它.
对于非eval方法,你尝试过类似的东西吗?
if ($orderby='b') then $foo/b else if ($orderby='c') then $foo/c else (),if ($orderby='b descending') then $foo/b else if ($orderby='c descending') then $foo/c else () descending
但是我可能会将键和方向分成两个不同的变量.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。