LINQ to XML with join和GroupBy()。它是否正确?

时间:2010-01-06 21:57:09

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

我正在学习LINQ,这似乎是一个相当简单的问题。我有一个半工作的解决方案,但我相信它可以清理。

propertyAuto节点表示id = 606的汽车。 此节点需要至少有两个子propertyValue节点,一个引用属性为“Book”且一个为“Auto”的vehicleValuation元素。 (我的代码还没有检查,它们可以是自动或现在预订)

最后,我需要获得同一辆车的Book值和Auto Value。

请注意,我将永远不会知道任何ID或idRef,并且将来会有多辆车。

现在这是我的代码(准备复制到LINQPad!)

var data = XElement.Parse (@"
<MyXML>
  <propertyAuto id='606'>
    <Values>
      <propertyValue idRef='f95d5dce-8152-4e9e-889e-7433d32664d6' />
      <propertyValue idRef='cd1a83a7-dd04-41f9-b31c-5408a38ac777' />
    </Values>
  </propertyAuto>
  <Valuations>
    <vehicleValuation id='cd1a83a7-dd04-41f9-b31c-5408a38ac777'
    valuationType='Auto' estimatedValue='8350.00' />
    <vehicleValuation id='f95d5dce-8152-4e9e-889e-7433d32664d6'
    valuationType='Book' estimatedValue='12475.00' />
  </Valuations>
</MyXML>");

var valuations = from property in data.Descendants("propertyValue")
                 join value in data.Descendants("vehicleValuation")
                 on
                    (string)property.Attribute("idRef")
                 equals
                    (string)value.Attribute("id")
                 where property.Parent.Descendants("propertyValue").Count() > 1
                 && ((string)value.Attribute("valuationType") == "Auto" || (string)value.Attribute("valuationType") == "Book")               
                 select new { Value = value.Attribute("estimatedValue").Value, Type = value.Attribute("valuationType").Value, PropertyID = property.Parent.Parent.Attribute("id").Value };

valuations.Dump();

var values = valuations.GroupBy(x=> x.PropertyID).FirstOrDefault();
string auto = values.Where(x => x.Type == "Auto").Select(x=>x.Value).First().ToString();
string book = values.Where(x => x.Type == "Book").Select(x=>x.Value).First().ToString();

auto.Dump();
book.Dump();

这是可行的还是我应该转移到xpath等?

2 个答案:

答案 0 :(得分:1)

 var valuations = el.Element("Valuations").Elements("vehicleValuation");
 var carNodes = el.Elements("propertyAuto");
 var cars = carNodes.Select(x => 
                new {
                     id = x.Attribute("id").Value,
                     PropertyValues = x.Element("Values").Elements("propertyValue").
                                        SelectMany(
                                                y => valuations.Where( 
                                                        val => val.Attribute("id").Value == y.Attribute("idRef").Value
                                                                      ).Select( valuation => 
                                                                          new { 
                                                                                Type = valuation.Attribute("valuationType"),
                                                                                EstVal = valuation.Attribute("estimatedValue")
                                                                              }
                                                                              )
                                               )
                     });

有点复杂,但这会创建一个匿名类型,其车辆ID与属性值匹配。

如果您想直接购买汽车自动和预订价值,您可以这样做。

var cars = carNodes.Select(car => 
                new {
                     id = car.Attribute("id").Value,
                     Auto = car.Element("Values").Elements("propertyValue").
                                        SelectMany(
                                                y => valuations.Where( 
                                                        val => val.Attribute("id").Value == y.Attribute("idRef").Value &&
                                                               val.Attribute("valuationType").Value == "Auto"
                                                                      )
                                                                .Select( valuation => valuation.Attribute("estimatedValue"))
                                               ).SingleOrDefault(),
                     Book = car.Element("Values").Elements("propertyValue").
                                          SelectMany(
                                                  y => valuations.Where(
                                                          val => val.Attribute("id").Value == y.Attribute("idRef").Value &&
                                                                 val.Attribute("valuationType").Value == "Book"
                                                                        )
                                                                  .Select(valuation => valuation.Attribute("estimatedValue"))
                                                 ).SingleOrDefault(),
                     });

答案 1 :(得分:1)

显然,您的解决方案是可行的,因为它可行!我还想进一步将结果作为一个具有您可以轻松检查的属性的汽车列表:

var carProperties = from propertyAuto in data.Descendants("propertyAuto")
                    select new
                    {
                        Id = propertyAuto.Attributes("id").First().Value,
                        Properties = from property in propertyAuto.Descendants("propertyValue")
                                     join value in data.Descendants("vehicleValuation")
                                     on property.Attribute("idRef").Value
                                     equals value.Attribute("id").Value
                                     select new
                                     {
                                         Value = value.Attribute("estimatedValue").Value,
                                         Type = value.Attribute("valuationType").Value,
                                         PropertyID = property.Parent.Parent.Attribute("id").Value
                                     }
                    };

var cars = from car in carProperties
           select new
           {
               Id = car.Id,
               Auto = car.Properties.Where(x => x.Type == "Auto").Select(x => x.Value).First(),
               Book = car.Properties.Where(x => x.Type == "Book").Select(x => x.Value).First()
           };

请注意,不再需要GroupBy。