2013-10-15 2 views
1

I've получил XML, как это:Группа необязательными столбцов с помощью Linq

<LiftFactors> 
    <Products> 
    <Product> 
     <ProductId>Limella</ProductId> 
     <Tactics> 
     <Tactic> 
      <Typ>PriceRed</Typ> 
      <TPRFrom>0</TPRFrom> 
      <TprThru>10</TprThru> 
      <Lift>14</Lift> 
      <VF>2012-01-09</VF> 
      <VT>2012-01-11</VT> 
     </Tactic> 
     <Tactic> 
      <Typ>PriceRed</Typ> 
      <TPRFrom>10 </TPRFrom> 
      <TprThru>20</TprThru> 
      <Lift>30</Lift> 
      <VF>2012-01-07</VF> 
      <VT>2012-20-08</VT> 
     </Tactic> 
     <Tactic> 
      <Typ>Display</Typ> 
      <Lift>14</Lift> 
      <VF>2012-01-04</VF> 
      <VT>2012-01-06</VT> 
     </Tactic> 
     </Tactics> 
    </Product> 
    <Product> 
     <ProductId>Empower Cola</ProductId> 
     <Tactics> 
      <Tactic> 
       <Typ>Display</Typ> 
       <Lift>20</Lift> 
       <VF>2012-01-01</VF> 
       <VT>2012-01-08</VT> 
      </Tactic> 
     </Tactics> 
    </Product> 
    </Products> 
</LiftFactors> 

со следующим утверждением LinQ I'm Получение Tactic данных, сгруппированных по ProductID и упорядоченные по дате ValidFrom:

var xml = XElement.Parse(theXML); 
var d = (from e in xml.Descendants(@"Product") 
      group e by e.Element("ProductId").Value into Items 
     select Items).ToDictionary 
     (x => x.Key, x => ((XElement)x.First()).Descendants("Tactic").ToList().OrderByDescending (y=> ((DateTime)y.Element("VF")))); 

Выход:

Limella -> Tactic PriceRed 1 
      -> Tactic PriceRed 2 
      -> Tactic Display 
    Empower Cola -> Tactic Display 

Теперь предположим узлы 'продукта' являются необязательными, и я могу дополнительно T Actic узлы вне узлов продукта:

<LiftFactors> 
    <Products> 
    <Product> 
     <ProductId>Limella</ProductId> 
     <Tactics> 
     <Tactic> 
      <Typ>PriceRed</Typ> 
      <TPRFrom>0</TPRFrom> 
      <TprThru>10</TprThru> 
      <Lift>14</Lift> 
      <VF>2012-01-09</VF> 
      <VT>2012-01-11</VT> 
     </Tactic> 
     </Tactics> 
    </Product> 
    </Products> 
    <Tactics> 
     <Tactic> 
      <Typ>PriceRed</Typ> 
      <TPRFrom>0</TPRFrom> 
      <TprThru>10</TprThru> 
      <Lift>14</Lift> 
      <VF>2012-01-09</VF> 
      <VT>2012-01-11</VT> 
     </Tactic> 
    </Tactics> 
</LiftFactors> 

Теперь то, что я хочу, это выход:

Limella -> Tactic 1 
     -> ... 
<Null> -> Tactic 2 
     -> .... 

Так что тактика должна также появиться в группе, не имеющей ключа, назначенного. Возможно ли это только с одним запросом linq?

ответ

1

Попробуйте это:

var d = xml.Descendants("Tactics") 
      .GroupBy(e=>e.Parent.Name.LocalName == "Product" ? 
         e.Parent.Element("ProductId").Value : "") 
      .ToDictionary(x => x.Key, x => ((XElement)x.First()) 
            .Descendants("Tactic").ToList() 
            .OrderByDescending (y=>(DateTime)y.Element("VF"))); 

ПРИМЕЧАНИЕ: группа, имеющие Tactics из сторона Product имеет ключ как empty string, вы можете немного изменить код (используя If-else), чтобы изменить его на null.

+0

Спасибо! Очень хорошо работает. –

1

Следующая, кажется, работает с вашим пример XML, это дает вам enumarable коллекцию анонимных объектов, поле идентификатор этих объектов заполняется, если Tactic находится внутри продукта, нуль в противном случае:

var xml = XElement.Parse(contents); 

var d = xml.Descendants("Tactic").Select(element => element.Parent != null ? new 
    { 
     id = element.Parent.Parent.Element("ProductId"), 
     Tactic = new 
      { 
       Typ = element.Descendants("Typ").FirstOrDefault().Value, 
       TPRFrom = element.Descendants("TPRFrom").FirstOrDefault().Value, 
       TprThru = element.Descendants("TprThru").FirstOrDefault().Value, 
       VF = element.Descendants("VF").FirstOrDefault().Value, 
       VT = element.Descendants("VT").FirstOrDefault().Value 
      } 
    } : null); 
+0

Это не работает с XML, который показал OP. Ваш код по-прежнему предполагает, что тактика находится в теге 'Product', который не является –

+0

Спасибо за ваши усилия JMK. Но, к сожалению, он не работает, как сказал Даниэль. –

Смежные вопросы