两个变量的xquery顺序不起作用

时间:2014-09-05 08:03:50

标签: xml sql-order-by xquery

在Xquery中,我想对xml示例进行排序,如下所示:

<library>
    <book>
         <author>abc</author>
         <author>def</author>
         <author>bcd</author>
    </book>
    <article>
         <author>utc</author>
         <author>abg</author>
    </article>
    <ebook>
         <author>zerg</author>
    </ebook>
</library>

我试图让输出成为..

<library>
    <article>
         <author>abg</author>
         <author>utc</author>
    </article>
    <book>
         <author>abc</author>
         <author>bcd</author>
         <author>def</author>
    </book>
    <ebook>
         <author>zerg</author>
    </ebook>
</library>

在我的查询中,我曾尝试过类似的内容:

for $s in //library
order by $s ascending, $s//* ascending
return $s

但是似乎没有接受&#34;顺序中的两个条件。

在我提出这个问题之前,我在这里找到了类似的帖子,但它与我正在寻找的解决方案无关。任何想法??

3 个答案:

答案 0 :(得分:1)

问题1:排序库与排序库内容

第一个问题是您只对<library/>容器元素进行排序。转而覆盖其所有孩子:/library/*

问题2:在不同级别上排序

此外,order by您只使用&#34;库项目&#34;上的订单。等级,因此您需要订购文章,书籍,电子书,如果有多个,则按作者姓名排序。这既不希望你想要实现也不想工作,因为你不能在一系列项目之后订购(在XQuery中没有为项目序列定义订单)。

要演示正在进行的操作,请稍微修改输入并限制第一个作者:

let $xml := document {
  <library>
    <book>
         <author>abc</author>
         <author>def</author>
         <author>bcd</author>
    </book>
    <article>
         <author>utc</author>
         <author>abg</author>
    </article>
    <article>
         <author>foobar</author>
    </article>
    <ebook>
         <author>zerg</author>
    </ebook>
  </library>
}

for $s in $xml//library/*
order by $s/name() ascending, ($s//*)[1] ascending
return $s

这将按预期列出所有文章,并根据第一作者的姓名对文章进行排序:

<article>
  <author>foobar</author>
</article>
<article>
  <author>utc</author>
  <author>abg</author>
</article>
<book>
  <author>abc</author>
  <author>def</author>
  <author>bcd</author>
</book>
<ebook>
  <author>zerg</author>
</ebook>

和解决方案

解决方案是构建新的结果元素,因此您还可以为每个项目的作者订购:

element library {
  for $item in /library/*
  let $name := local-name($item)
  order by $item
  return element { $name } {
    for $author in $item/author
    order by $author
    return $author
  }
}

答案 1 :(得分:1)

我讨厌通过建议语言B的解决方案来回答语言A中的解决方案的请求,但是你在这里做的事情属于XSLT比XQuery更好处理的问题类。

在XSLT中,可以使用单个模板规则来完成,该规则是完全通用的,不会对XML的实际内容做出任何假设:

<xsl:template match="*">
  <xsl:copy>
    <xsl:apply-templates select="*">
      <xsl:sort select="name()"/>
      <xsl:sort select="."/>
    </xsl:apply-templates>
  </xsl:copy>
</xsl:template>

答案 2 :(得分:0)

您需要嵌套查询才能执行此操作:

<library>{
  for $item in /library/*
    order by name($item)
  return 
   element {node-name($item)} {
     for $author in $item/author
       order by $author
     return $author
   }
}</library>