使用 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数据创建匿名或真实对象)