XQuery将xml元素分组

时间:2014-11-24 19:43:05

标签: xquery

我在xquery中尝试了一些分组

<Sheets>
    <Sheet>
        <ROI>5350</ROI>
        <TPI>830</TPI>
    </Sheet>
    <Sheet>
        <ROI>5459</ROI>
        <TPI>830</TPI>
    </Sheet>
    <Sheet>
        <ROI>5350</ROI>
        <TPI>856</TPI>
    </Sheet>
    <Sheet>
        <ROI>5678</ROI>
        <TPI>856</TPI>
    </Sheet>
    <Sheet>
        <ROI>17473</ROI>
        <TPI>856</TPI>
    </Sheet>
    <Sheet>
        <ROI>5350</ROI>
        <TPI>857</TPI>
    </Sheet>
    <Sheet>
        <ROI>5713</ROI>
        <TPI>857</TPI>
    </Sheet>
</Sheets>

在我的xquery中,我想传递一个动态值,说4号...我希望我的xml分组到4个Sheet元素到一组像

<Sheets>
    <set>
    <Sheet>
        <ROI>5350</ROI>
        <TPI>830</TPI>
    </Sheet>
    <Sheet>
        <ROI>5459</ROI>
        <TPI>830</TPI>
    </Sheet>
    <Sheet>
        <ROI>5350</ROI>
        <TPI>856</TPI>
    </Sheet>
    <Sheet>
        <ROI>5678</ROI>
        <TPI>856</TPI>
    </Sheet>
    </set>
    <set>
    <Sheet>
        <ROI>17473</ROI>
        <TPI>856</TPI>
    </Sheet>
    <Sheet>
        <ROI>5350</ROI>
        <TPI>857</TPI>
    </Sheet>
    <Sheet>
        <ROI>5713</ROI>
        <TPI>857</TPI>
    </Sheet>
    </set>
</Sheets>

喜欢,将4张纸分组到一组,其他4到1组,最后剩下的一套到一组

2 个答案:

答案 0 :(得分:1)

如果你有XQuery 3.0,你可以使用tumbling window来轻松实现这一目标:

xquery version "3.0";

let $group-size := 4  (: set your group size here :)
return

    <Sheets>
    {
       for tumbling window $window in /Sheets/Sheet
       start at $start when fn:true()
       end at $end when $end - $start eq $group-size - 1
       return
           <set>{$window}</set>
    }   
    </Sheets>

否则,如果您只有XQuery 1.0可用,则可以使用简单的FLWOR表达式和位置谓词来执行此操作:

xquery version "1.0";

let $group-size := 4  (: set your group size here :)
return

    <Sheets>
    {
        for $group in (1 to round(count(/Sheets/Sheet) div $group-size) cast as xs:integer)
        let $start := (1 * ($group - 1) * $group-size) + 1
        let $end := $group * $group-size
        return
            <set>{/Sheets/Sheet[position() ge $start][position() le $end]}</set>
    }
    </Sheets>

答案 1 :(得分:0)

您可以使用subsequence()并递归调用函数。

示例...

XML输入

<Sheets>
    <Sheet>
        <ROI>5350</ROI>
        <TPI>830</TPI>
    </Sheet>
    <Sheet>
        <ROI>5459</ROI>
        <TPI>830</TPI>
    </Sheet>
    <Sheet>
        <ROI>5350</ROI>
        <TPI>856</TPI>
    </Sheet>
    <Sheet>
        <ROI>5678</ROI>
        <TPI>856</TPI>
    </Sheet>
    <Sheet>
        <ROI>17473</ROI>
        <TPI>856</TPI>
    </Sheet>
    <Sheet>
        <ROI>5350</ROI>
        <TPI>857</TPI>
    </Sheet>
    <Sheet>
        <ROI>5713</ROI>
        <TPI>857</TPI>
    </Sheet>
</Sheets>

XQuery($groupSize传递为4

declare variable $groupSize external;

declare function local:group($set as node()*, $size as xs:integer) as item()* {
    <set>{subsequence($set,1,$size)}</set>,
    if (count($set)>$groupSize) then
        local:group(subsequence($set,$groupSize+1),$groupSize)
    else
        ()
};

<Sheets>{local:group(/*/*,$groupSize)}</Sheets>

XML输出

<Sheets>
   <set>
      <Sheet>
        <ROI>5350</ROI>
        <TPI>830</TPI>
      </Sheet>
      <Sheet>
        <ROI>5459</ROI>
        <TPI>830</TPI>
      </Sheet>
      <Sheet>
        <ROI>5350</ROI>
        <TPI>856</TPI>
      </Sheet>
      <Sheet>
        <ROI>5678</ROI>
        <TPI>856</TPI>
      </Sheet>
   </set>
   <set>
      <Sheet>
        <ROI>17473</ROI>
        <TPI>856</TPI>
      </Sheet>
      <Sheet>
        <ROI>5350</ROI>
        <TPI>857</TPI>
      </Sheet>
      <Sheet>
        <ROI>5713</ROI>
        <TPI>857</TPI>
      </Sheet>
   </set>
</Sheets>