2009-04-17 66 views
3

Grettings!Linq問題:合併條款

我有一些XML,看起來像這樣:

<Root> 
    <SectionA> 
     <Item id="111"> 
      <Options> 
       <Option val="a" cat="zzz"> 
        <Package value="apple" /> 
        <Feature value="avacado" /> 
       </Option> 
       <Option val="b" cat="yyy"> 
        <Package value="banana" /> 
        <Feature value="blueberry" /> 
       </Option> 
      </Options> 
     </Item> 
     <Item id="222"> 
      <Options> 
       <Option val="c" cat="xxx"> 
        <Package value="carrot" /> 
        <Feature value="cucumber" /> 
       </Option> 
       <Option val="d" cat="www"> 
        <Package value="dairy" /> 
        <Feature value="durom" /> 
       </Option> 
      </Options> 
     </Item> 
    </SectionA> 
    <SectionB> 
    . 
    . 
    . 
    </SectionB> 
</Root> 

我想基於項目是「111」的ID屬性,一個選項是「的VAL屬性來獲得包和特徵值一個」。

我不確定從哪裏開始。我可以使用where來選擇ITEM節點,但我不確定如何將它與OPTION節點上的where子句結合起來。有任何想法嗎?使用的SelectMany

var doc = XDocument.Parse(xml); 
var items = from i in doc.Descendants("Item") 
      from o in i.Descendants("Option") 
      where i.Attribute("id").Value == "111" 
       && o.Attribute("val").Value == "a" 
     select new { 
      Package = i.Descendants("Package").Attribute("value").Value, 
      Feature = i.Descendants("Feature").Attribute("value").Value      
     }; 

回答

7

這對我的作品。

var doc = XDocument.Parse(s); 

var items = from item in doc.Descendants("Item") 
      where item.Attribute("id").Value == "111" 
      from option in item.Descendants("Option") 
      where option.Attribute("val").Value == "a" 
      let package = option.Element("Package").Attribute("value") 
      let feature = option.Element("Feature").Attribute("value") 
      select new { Package = package.Value, Feature = feature.Value }; 

items.First().Feature; // = "avacado" 
items.First().Package; // = "apple" 

可以省略let部分,如果你想,他們只讓匿名類型更薄。

var items = from item in doc.Descendants("Item") 
      where item.Attribute("id").Value == "111" 
      from option in item.Descendants("Option") 
      where option.Attribute("val").Value == "a" 
      select new 
      { 
       Package = option.Element("Package").Attribute("value").Value, 
       Feature = option.Element("Feature").Attribute("value").Value 
      }; 

其實我有點像第二個。


而非查詢Linq風格。

var items = doc.Descendants("Item") 
       .Where(item => item.Attribute("id").Value == "111") 
       .SelectMany(item => item.Descendants("Option")) 
       .Where(option => option.Attribute("val").Value == "a") 
       .Select(option => new 
       { 
       Package = option.Element("Package").Attribute("value").Value, 
       Feature = option.Element("Feature").Attribute("value").Value 
       }); 
+0

+1,因爲你的管道看起來效率最高 – bendewey 2009-04-17 02:28:26

4

替代實現是一個自下而上的方法:

var items = xdoc 
      .Descendants("Option") 
      .Where(o => (string)o.Attribute("val") == "a" && (int)o.Ancestors("Item").Single().Attribute("id") == 111) 
      .Select(o => new { 
       Package = o.Element("Package"), 
       Feature= o.Element("Feature") 
      }); 
+0

我得到試圖獲得包和功能的值時,以下幾點: 「不包含'Attribute'的定義。 – Bullines 2009-04-17 01:30:06

0

這裏

0

這裏是VB版(VB真的岩石++中XML的東西):

Module Module1 

    Sub Main() 
     Dim xml As XElement = <Root> 
            <SectionA> 
             <Item id="111"> 
              <Options> 
               <Option val="a" cat="zzz"> 
                <Package value="apple"/> 
                <Feature value="avacado"/> 
               </Option> 
               <Option val="b" cat="yyy"> 
                <Package value="banana"/> 
                <Feature value="blueberry"/> 
               </Option> 
              </Options> 
             </Item> 
             <Item id="222"> 
              <Options> 
               <Option val="c" cat="xxx"> 
                <Package value="carrot"/> 
                <Feature value="cucumber"/> 
               </Option> 
               <Option val="d" cat="www"> 
                <Package value="dairy"/> 
                <Feature value="durom"/> 
               </Option> 
              </Options> 
             </Item> 
            </SectionA> 
            <SectionB>          
            </SectionB> 
           </Root> 

     Dim data = From x In xml...<Option> _ 
        Where x.Ancestors("Item")[email protected] = "111" AndAlso [email protected] = "a" _ 
        Select Package = x.<Package>[email protected], _ 
          Feature = x.<Feature>[email protected] 

     For Each item In data 
      Console.WriteLine("Package: {0}, Feature: {1}", item.Package, item.Feature) 
     Next 
     Stop 
    End Sub 

End Module