具有 join 和 GroupBy() 的 LINQ to XML。这是正确的吗?

发布于 2024-08-17 08:25:18 字数 1988 浏览 6 评论 0原文

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

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

最后,我需要获取同一辆车的预订价值和汽车价值。

请注意,我永远不会事先知道任何 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 等?

I am learning LINQ and this seems like a fairly simple problem. I have a semi-working solution but I am sure it could be cleaned up.

The propertyAuto node represents a car with id = 606.
This node needs to have at least two child propertyValue nodes, one that references a vehicleValuation element with attribute of "Book" and one of "Auto". (My code doesnt check this yet, they could both be Auto or Book now)

Finally, I need to get the Book value and Auto Value for the same car.

Note that I will never know any IDs or idRef's beforehand and in the future there will be multiple cars.

Here is my code now (ready to copy into 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();

Is this workable or should I move to xpath, etc?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

北笙凉宸 2024-08-24 08:25:18

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

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。

Clearly your solution is workable because it works! I would also take it a little further to get the results as a list of cars with properties that you can easily inspect:

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

Notice that the GroupBy is no longer needed.

毁虫ゝ 2024-08-24 08:25:18
 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(),
                     });
 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")
                                                                              }
                                                                              )
                                               )
                     });

A bit complicated, but this will create an anonymous type that has the cars ID matched to Property Values.

If you want the cars Auto and Book value directly you can do something like this.

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(),
                     });
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文