2014-09-30 48 views
0

我有一个XML文档,其中包含客户及其订单和这些订单中的项目列表。我想获得一个包含不同客户价值的清单。客户的ID是“Name”的属性。例如XML:XQuery - 通过属性提取不同的元素

<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

首先,您的第一行XQuery具有'/ customerunion /',而XML具有'':在元素名称中间有's'。你的第二个'let'语句完全抛弃了'/ customersunion /'。由于这些原因,你的前两个变量将不包含任何内容。 – LarsH 2014-09-30 03:26:30

+1

请进行一些基本的调试_before_提问。只运行第一行(并返回结果),如果没问题,继续下一行(或逻辑代码块,或任何合理的基本单位)。 – 2014-09-30 07:01:04

+0

要添加到Jens的正确评论中,您可能有兴趣了解可用于调试的'fn:trace()'函数。 – dirkk 2014-09-30 07:23:40

回答

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是某个数字。如果不是这种情况,您需要调整或从查询中删除该行。