【问题标题】:Linq Question: Combined Where ClausesLinq 问题:组合 Where 子句
【发布时间】:2009-04-17 00:37:02
【问题描述】:

您好!

我有一些看起来像这样的 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”和 OPTION 的 VAL 属性为“a”来获取 PACKAGE 和 FEATURE 值。

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

【问题讨论】:

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


    【解决方案1】:

    这对我有用。

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 我在尝试获取包和功能的值时得到以下信息:“不包含‘属性’的定义”。
      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

        这里是 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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-06
          • 1970-01-01
          • 1970-01-01
          • 2016-04-23
          • 2021-09-06
          相关资源
          最近更新 更多