使用 LINQ 解析 XML 数据

Posted

技术标签:

【中文标题】使用 LINQ 解析 XML 数据【英文标题】:Parsing XML Data with LINQ 【发布时间】:2010-11-25 08:46:36 【问题描述】:

我是 LINQ 新手,迫切需要快速完成这个项目。我需要为每个 MPrice 返回带有正确价格信息的 ID。任何建议都非常感谢!这是 XML 的一个示例:

<Pricing>
<MPrice>
    <Id>0079</Id>
      <Price>
        <Price>31.25</Price>
        <StartDt>2009-8-01</StartDt>
        <EndDt>2009-08-26</EndDt>
      </Price>
      <Price>
        <ListPrice>131.25</ListPrice>
        <StartDt>2009-08-26</StartDt>
        <EndDt>9999-12-31</EndDt>
       </Price>
   </MPrice>
   <MPrice>
    <Id>0081</Id>
      <Price>
        <Price>131.25</Price>
        <StartDt>2009-8-01</StartDt>
        <EndDt>2009-08-26</EndDt>
      </Price>
      <Price>
        <ListPrice>231.25</ListPrice>
        <StartDt>2009-08-26</StartDt>
        <EndDt>9999-12-31</EndDt>
       </Price>
   </MPrice> 
</Pricing>

【问题讨论】:

【参考方案1】:

这是一种方法:

using System;
using System.Linq;
using System.Xml.Linq;

class Program

    static void Main()
    
        String xml = @"<Pricing>
            <MPrice>
                <Id>0079</Id>
                <Price>
                <Price>31.25</Price>
                <StartDt>2009-8-01</StartDt>
                <EndDt>2009-08-26</EndDt>
                </Price>
                <Price>
                <ListPrice>131.25</ListPrice>
                <StartDt>2009-08-26</StartDt>
                <EndDt>9999-12-31</EndDt>
                </Price>
            </MPrice>
           </Pricing>";

        var priceInfo = from e in XElement.Parse(xml).Elements("MPrice").Elements("Price")
                let start = DateTime.Parse(e.Descendants("StartDt").FirstOrDefault().Value)
                let end = DateTime.Parse(e.Descendants("EndDt").FirstOrDefault().Value)
                where start < DateTime.Now && end > DateTime.Now
                select new  Id = e.Parent.Element("Id").Value, ListPrice = e.Element("ListPrice").Value ;

        Console.WriteLine(priceInfo.FirstOrDefault().Id);
        Console.WriteLine(priceInfo.FirstOrDefault().ListPrice);
    

输出:

0079
131.25

请注意,需要进行比此示例提供的更多的错误检查。我会特别添加对日期时间解析的检查(可能通过使用包装DateTime.TryParseExact 的函数)。

编辑:如果您想使用XDocument 而不是XElement,您需要对查询进行细微的更改(注意使用Descendants 方法而不是Elements 方法):

var priceInfo = from e in XDocument.Parse(xml).Descendants("MPrice").Elements("Price")
        let start = DateTime.Parse(e.Descendants("StartDt").FirstOrDefault().Value)
        let end = DateTime.Parse(e.Descendants("EndDt").FirstOrDefault().Value)
        where start < DateTime.Now && end > DateTime.Now
        select new  Id = e.Parent.Element("Id").Value, ListPrice = e.Element("ListPrice").Value ;

请记住,您不需要使用XDocument,除非您将 XML 作为真正的文档使用。在大多数情况下,XElement 类型就足够了。

编辑#2:如果您想从磁盘加载XDocument,请使用以下方法:

using System;
using System.Linq;
using System.Xml.Linq;

class Program

    static void Main()
    
        XDocument document = XDocument.Load(@"d:\test.xml");

        var priceInfo = from e in document.Descendants("MPrice").Elements("Price")
                let start = DateTime.Parse(e.Descendants("StartDt").FirstOrDefault().Value)
                let end = DateTime.Parse(e.Descendants("EndDt").FirstOrDefault().Value)
                where start < DateTime.Now && end > DateTime.Now
                select new  Id = e.Parent.Element("Id").Value, ListPrice = e.Element("ListPrice").Value ;

        Console.WriteLine(priceInfo.FirstOrDefault().Id);
        Console.WriteLine(priceInfo.FirstOrDefault().ListPrice);
    

【讨论】:

我可以用 XDocument 代替 XElement 做同样的解析吗? 似乎仍然不起作用。我正在使用:XDocument xmlDoc = XDocument.Load("my.xml");现在,当我调用: XDocument.Parse(xml).Descendants("MPrice").Elements("Price") 我收到未将 XDocument 转换为字符串的错误。有什么想法吗? 如果您已经将 XML 加载到 XDocument 中,则无需调用 XDocument.Parse。我将再次编辑以演示如何处理磁盘上的 XML 文件。 感谢您的时间和帮助。这个项目几乎完成了,我学到了一些新东西。谢谢【参考方案2】:
string id = yourDocument
                .Descendants("Pricing")
                .Descendants<XElement>("MPrice")
                .Where<XElement>(i => i.Descendants("Price")
                                        .Descendants<XElement>("StartDt")
                                        .Select<XElement, DateTime>(s => DateTime.Parse(s.Value))
                                        .FirstOrDefault<DateTime>().Date == DateTime.Now.Date)
                .Select<XElement, string>(i => i.Descendants("Id").FirstOrDefault<XElement>().Value)
                .FirstOrDefault<string>();

假设 id 是一个字符串,这应该可以工作。您可以将其设为 int。

你应该做一些检查以确保日期是正确的等等...... . ,但这是一个快速示例,如果开始日期更改为 2009-9-03 或当前日期日期,则它应该适用于给定的 Xml 示例。

【讨论】:

以上是关于使用 LINQ 解析 XML 数据的主要内容,如果未能解决你的问题,请参考以下文章

csharp 使用LINQ 2 XML将XML数据条目解析为C#对象的简单示例

在 C# 中使用 LINQ-To-XML 解析具有多个列表和类对象的 XML 数据

使用LINQ的简单XML解析(从XML数据创建匿名或真实对象)

使用 C# LINQ 解析 XML 文档

无法使用 Xdocument 和 Linq 解析 xml 字符串

无法使用 LINQ 解析 XML 文件中的属性