XQuery - 按属性提取不同的元素

时间:2014-09-30 01:13:46

标签: xml xpath xquery exist-db

我有一个XML文档,其中包含客户及其订单和订单中的项目列表。我想获得一个包含不同客户价值的列表。客户的ID是“名称”的属性。示例XML:

<customerunion>
  <Customer Name="c2">
    <Order OrderNumber="o1">
      <Item Description="xyz">i10</Item>
    </Order>
  </Customer>

 <Customer Name="c3">
    <Order OrderNumber="o1">
      <Item Description="qwe">i11</Item>
      <Item Description="mnb">i12</Item>
    </Order>
    <Order OrderNumber="o2">
      <Item Description="cfg">i5</Item>
    </Order>
 </Customer>

 <Customer Name="c1">
    <Order OrderNumber="o1">
      <Item Description="abc">i1</Item>
      <Item Description="def">i2</Item>
    </Order>
 </Customer>

 <Customer Name="c4">
    <Order OrderNumber="o1">
      <Item Description="abc">i1</Item>
    </Order>
    <Order OrderNumber="o2">
      <Item Description="def">i2</Item>
    </Order>
 </Customer>

 <Customer Name="c2">
    <Order OrderNumber="o1">
      <Item Description="milk"/>
 </Order>
 </Customer>

 <Customer Name="c10">
    <Order OrderNumber="o1">
      <Item Description="chips greek yogort avacado"/>
    </Order>
 </Customer>

 <Customer Name="c4">
    <Order OrderNumber="o1">
      <Item Description="tea bags cheese"/>
    </Order>
 </Customer>

 <Customer Name="c11">
    <Order OrderNumber="o1">
      <Item Description=" milk sushi Notebook "/>
    </Order>
 </Customer>

 <Customer Name="c11">
    <Order OrderNumber="o2">
      <Item Description="grape tomato"/>
    </Order>
 </Customer>

 <Customer Name="c12">
    <Order OrderNumber="o1">
      <Item Description="bread"/>
    </Order>
 </Customer>
</customerunion>

以下是我想得到的结果:

<customerlib>
  <Customer Name="c1">
    <Order OrderNumber="o1">
      <Item Description="abc">i1</Item>
      <Item Description="def">i2</Item>
    </Order>
  </Customer>

  <Customer Name="c2">
    <Order OrderNumber="o1">
      <Item Description="xyz">i10</Item>
    </Order>
  </Customer>

  <Customer Name="c3">
    <Order OrderNumber="o1">
      <Item Description="qwe">i11</Item>
      <Item Description="mnb">i12</Item>
    </Order>
    <Order OrderNumber="o2">
      <Item Description="cfg">i5</Item>
    </Order>
  </Customer>
  <Customer Name="c4">
    <Order OrderNumber="o1">
      <Item Description="abc">i1</Item>
    </Order>
    <Order OrderNumber="o2">
      <Item Description="def">i2</Item>
    </Order>
  </Customer>
  <Customer Name="c10">
    <Order OrderNumber="o1">
      <Item Description="chips">i1</Item>
      <Item Description="greek yogort">i2</Item>
      <Item Description="avacado">i3</Item>
    </Order>
  </Customer>

  <Customer Name="c11">
    <Order OrderNumber="o1">
      <Item Description="milk">i1</Item>
      <Item Description="sushi">i2</Item>
      <Item Description="Notebook">i3</Item>
    </Order>
    <Order OrderNumber="o2">
      <Item Description="grape tomato">i1</Item>
    </Order>
  </Customer>

  <Customer Name="c12">
    <Order OrderNumber="o1">
      <Item Description="bread">i1</Item>
    </Order>
  </Customer>
</customerlib>

我使用了以下XQuery:

let $customer := doc("customerunion.xml")/customerunion/Customer
let $allcustomername := doc("customerunion.xml")/Customer/@Name
for $uniquecustomer in distinct-values($customer/@Name)
let $order := distinct-values($customer[Name=$uniquecustomer]/Order)
let $item := distinct-values($customer[Name=$uniquecustomer]/Order/Item)
where $uniquecustomer = $allcustomername
return 
 <customerlib>
    {$uniquecustomer/..}
    {
      for $o in $order
      return $o
    }
    {
      for $i in $item
      return $i
    }
 </customerlib>

但是,我没有得到运行查询的结果。你能帮我修改一下XQuery来得到想要的结果吗?

1 个答案:

答案 0 :(得分:2)

如果我理解正确,在我看来,您要求将所有订单分组到不同的客户中?

如果是这样,在eXist-db中,您可以使用XQuery 3.0中的group by表达式。因此,以下查询应该适合您:

<customerlib>
{
    let $customers := doc("customerunion.xml")
    return
        for $customer in $customers/customersunion/Customer
        group by $customer-name := $customer/@Name
        order by substring-after($customer-name, "c") cast as xs:integer
        return
            <Customer Name="{$customer-name}">
            {
                $customers/customersunion/Customer[@Name eq $customer-name]/Order
            }
            </Customer>
}
</customerlib>

我还添加了一个order by表达式,因为您显示的结果是有序的。但是,这可以基于以下事实:您的客户名称始终采用cN格式,其中N是某个数字。如果不是这种情况,则需要从查询中调整或删除该行。