在我们的程序中,我们经常需要将一些系统的数据、信息保存在文件中,而不是保存在数据库中,在.NET中,我通常都是选择将这些系统的数据、信息保存在XML中。
操作XML的技术有很多种:
1)DOM(Document Object Model,文档对象模型),它为XML文档提供了一个标准的解析。
2)XPath和XSLT,它们提供了查询和格式化XML的功能。
3).NET框架中提供了一些对XML操作的类(在System.XML命名空间下)。
4)LINQ to XML。
在我看来有了LINQ to XML技术,.NET中其它操纵XML的技术都可以弃而不用了,因为LINQ to XML操纵XML比其它技术都更简单更方便也更直观。
LINQ to XML 是基于LINQ的,所以可以使用LINQ的所有功能,如标准查询操作符(详细可阅读《LINQ标准查询操作符详解》)和LINQ的编程接口。使用LINQ to XML可以很方便地将XML文件加载到内存中,对XML文档中的节点进行查询修改删除等各种操作,然后又可以很方便地将操作后的XML文档保存回磁盘。
System.Xml.Linq的命名空间中包含了LINQ to XML处理XML用到的所有类,共有19个类,如下所示。
类 说明 Extensions 包含 LINQ to XML 扩展方法。 XAttribute 表示一个 XML 特性。 XCData 表示一个包含 CDATA 的文本节点。 XComment 表示一个 XML 注释。 XContainer 表示可包含其他节点的节点。 XDeclaration 表示一个 XML 声明。 XDocument 表示 XML 文档。 XDocumentType 表示 XML 文档类型定义 (DTD)。 XElement 表示一个 XML 元素。 XName 表示 XML 元素或特性的名称。 XNamespace 表示一个 XML 命名空间。 此类不能被继承。 XNode 表示 XML 树中节点的抽象概念(元素、注释、文档类型、处理指令或文本节点)。 XNodeDocumentOrderComparer 包含用于比较节点的文档顺序的功能。 无法继承此类。 XNodeEqualityComparer 比较节点以确定其是否相等。 无法继承此类。 XObject 表示 XML 树中的节点或特性。 XObjectChangeEventArgs 提供有关 Changing 和 Changed 事件的数据。 XProcessingInstruction 表示 XML 处理指令。 XStreamingElement 表示支持延迟流输出的 XML 树中的元素。 XText 表示一个文本节点。
这19个类提供了很多很多的方法,事实上很少人会在学习LINQ to XML的时候去学习每一种的方法的细节,本文的目的是让从来没有使用过LINQ to XML的童鞋在需要使用LINQ to XML技术的时候快速上手,然后用之于自己的程序开发中,所以本文只讲LINQ to XML处理XML类中最常用、用到最多的三个类,分别是XDocument、XElement和XAttribute。
XDocument类派生于XContainer类,因此它可以有子节点,但XML的标准限制了XDocument对象只包含单个XElement子节点,因为XML文档只允许有一个根节点。
XDocument提供了处理有效XML文档,包括声明、注释和处理指令。
XDocument 可以包含以下元素:
1)一个 XDeclaration 对象。 XDeclaration 使您能够指定 XML 声明的相关部分:XML 版本、文档的编码以及 XML 文档是否是独立的。
2)一个 XElement 对象。 这是 XML 文档的根节点。
3)任意数目的 XProcessingInstruction 对象。 处理指令将信息传递给处理 XML 的应用程序。
4)任意数目的 XComment 对象。 注释将与根元素同级。 XComment 对象不能是列表中的第一个参数,因为 XML 文档以注释开头无效。
5)一个用于 DTD 的 XDocumentType。
XDocument类提供的方法可参考MSDN文档。
XElement派生自XContainer,而XContainer又派生于XNode类,所以一个元素也是一个节点。通过XElement可以创建XML的元素,添加和修改,移除元素以及子元素。
XElement类提供了很多方法,因为一个XML文档中最为核心的东西就是XElement,这些方法使得我们处理XML提供如囊中取物般简单。
XElement类提供的方法可以参考MSDN文档。
XAttribute派生于XObject类,不是派生于XNode类,所以XAttribute不能作为XML树中的节点,它是与XElement相关联的名称/值对,也就是XAttibute不能独立于元素而存在。
XAttribute类提供的方法可参考MSDN文档。
本文的重点是讲述如何用LINQ to XML技术操纵XML文档,包含如何创建一个XML文档,如何保存XML文档,如何遍历XML文档元素,如何查找XML文档元素,如何更新XML文档的元素,如何删除XML文档元素等,下面我们假设一个应用场景来使用LINQ to XML技术来实现刚才所说的种种操作。
场景:将中国的省市区信息保存在一个XML文档中,可以方便地对该文档进行各种操作,如查询,更新,删除元素等。
下面我们先创建省市区的相关类,如下:
public class Province
{
/// <summary>
/// 省份名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 省会
/// </summary>
public string Capital { get; set; }
}
public class City
{
/// <summary>
/// 城市名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 城市编号
/// </summary>
public string Code { get; set; }
public Province Province { get; set; }
}
public class District
{
/// <summary>
/// 区名
/// </summary>
public string Name { get; set; }
/// <summary>
/// 描述
/// </summary>
public string Description { get; set; }
public City City { get; set; }
}
1)如何创建一个保存中国省市区信息的XML文档。
使用LINQ to XML 创建一个XML文档非常简单,代码如下:
static void Main(string[] args)
{
//
获取当前应用程序目录下Area.xml文件的路径
string _filePath = Path.Combine(System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "Area.xml");
FileInfo fiXML = new FileInfo(_filePath);
//如果文件不存在
if (!(fiXML.Exists))
{
XDocument xelLog = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XComment("XML File For AREA"),
new XElement("Provinces",
new XElement("Province", new XAttribute("Name", "省份"),
new XElement("City", new XAttribute("Name", "城市"),
new XElement("District", new XAttribute("Name", "行政区")))
)
)
);
xelLog.Save(_filePath);
}
}
这段代码使用指定的内容初始化XDocument类的新实例,然后调用XDocument的Save方法来生成一个XML文档。很少使用XDocument来创建XML树,通常是使用 XElement 根节点创建 XML 树。除非具有创建文档的具体要求(例如,必须在顶级创建处理指令和注释,或者必须支持文档类型),否则使用 XElement 作为根节点通常会更方便。运行这段代码,就会在生成的应用程序根目录下创建一个名为Area.xml的文档,文档内容如下:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!--XML File For AREA-->
<Provinces>
<Province Name="省份">
<City Name="城市">
<District Name="行政区" />
</City>
</Province>
</Provinces>
2)如何将一个XML树加载到程序内存。
我们操作一个XML文档首先是需要将该文档加载到程序的内存中,在LINQ to XML中,通常是使用XElement类型的Load方法将XML文档自根节点开始的XML树加载到一个XElement类型的对象中,然后我们就可以采用XElement提供的各种方法对这个内存中XML文档进行各种操作。
我们创建一个LINQtoXML的帮助类LinqToXmlHelper.cs,将对XML操作的相关方法都写在这个类里面,下面是一个加载XML文档到XElement对象的方法。
/// <summary>
/// 将Area.xml文档加载到内存中的XElement类型的对象xElement,成功调用 XElement.Load方法后会在xElement保存整棵XML树
/// </summary>
/// <returns></returns>
public XElement Load()
{
XElement xElement = XElement.Load(_filePath);
return xElement;
}
我们刚才已经创建了一个XML文档,现在我们将这个文档加载到内存中,然后打印这个XElement对象。
static void Main(string[] args)
{
LinqToXmlHelper linqToXmlHelper = new LinqToXmlHelper();
var elements = linqToXmlHelper.Load();
string str = elements.ToString();
Console.WriteLine(str);
Console.ReadKey();
}