Linq问题:结合Where子句

时间:2009-04-17 00:37:02

标签: c# .net linq linq-to-xml

素不相识!

我有一些看起来像这样的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>

我想根据ITEM的ID属性为“111”获取PACKAGE和FEATURE值,OPTION的VAL属性为“a”。

我不知道从哪里开始。我可以使用where选择ITEM节点,但我不确定如何将它与OPTION节点上的where子句相结合。有什么想法吗?

4 个答案:

答案 0 :(得分: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
               });

答案 1 :(得分:4)

使用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                     
         };

答案 2 :(得分:0)

这是一种自下而上的方法:

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") 
            });

答案 3 :(得分: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").@id = "111" AndAlso x.@val = "a" _
                   Select Package = x.<Package>.@value, _
                          Feature = x.<Feature>.@value

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

End Module