新手如何快速上手LINQ to XML

开发 前端
本文的目的是让从来没有使用过LINQ to XML的童鞋在需要使用LINQ to 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个类,如下所示。

类                                    说明

 

[[37481]]

Extensions                     包含 LINQ to XML 扩展方法。

 

 

[[37481]]

XAttribute                       表示一个 XML 特性。

 

 

[[37481]]

XCData                          表示一个包含 CDATA 的文本节点。

 

 

[[37481]]

XComment                     表示一个 XML 注释。

 

 

[[37481]]

XContainer                    表示可包含其他节点的节点。

 

 

[[37481]]

XDeclaration                  表示一个 XML 声明。

 

 

[[37481]]

XDocument                    表示 XML 文档。

 

 

[[37481]]

XDocument                    Type表示 XML 文档类型定义 (DTD)。

 

 

[[37481]]

XElement                       表示一个 XML 元素。

 

 

[[37481]]

XName                            表示 XML 元素或特性的名称。

 

 

[[37481]]

XNamespace                   表示一个 XML 命名空间。 此类不能被继承。

 

 

[[37481]]

XNode                             表示 XML 树中节点的抽象概念(元素、注释、文档类型、处理指令或文本节点)。

 

 

[[37481]]

XNodeDocumentOrderComparer            包含用于比较节点的文档顺序的功能。 无法继承此类。

 

 

[[37481]]

XNodeEqualityComparer                        比较节点以确定其是否相等。 无法继承此类。

 

 

[[37481]]

XObject                                                  表示 XML 树中的节点或特性。

 

 

[[37481]]

XObjectChangeEventArgs                     提供有关 Changing 和 Changed 事件的数据。

 

 

[[37481]]

XProcessingInstruction                          表示 XML 处理指令。

 

 

[[37481]]

XStreamingElement                               表示支持延迟流输出的 XML 树中的元素。

 

 

[[37481]]

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文档中,可以方便地对该文档进行各种操作,如查询,更新,删除元素等。

下面我们先创建省市区的相关类,如下:

  1. public class Province  
  2.     {  
  3.        /// <summary> 
  4.        /// 省份名称  
  5.        /// </summary> 
  6.        public string Name { get; set; }  
  7.        /// <summary> 
  8.        /// 省会  
  9.        /// </summary> 
  10.        public string Capital { get; set; }  
  11.  
  12.     }  
  13.  
  14.     public class City  
  15.     {  
  16.         /// <summary> 
  17.         /// 城市名称  
  18.         /// </summary> 
  19.         public string Name { get; set; }  
  20.         /// <summary> 
  21.         /// 城市编号  
  22.         /// </summary> 
  23.         public string Code { get; set; }  
  24.  
  25.         public Province Province { get; set; }  
  26.     }  
  27.  
  28.     public class District  
  29.     {  
  30.         /// <summary> 
  31.         /// 区名  
  32.         /// </summary> 
  33.         public string Name { get; set; }  
  34.  
  35.         /// <summary> 
  36.         /// 描述  
  37.         /// </summary> 
  38.         public string Description { get; set; }  
  39.  
  40.         public City City { get; set; }  
  41.     } 

1)如何创建一个保存中国省市区信息的XML文档。

使用LINQ to XML 创建一个XML文档非常简单,代码如下:

  1. static void Main(string[] args)  
  2.         {  
  3.             //获取当前应用程序目录下Area.xml文件的路径  
  4.             string _filePath = Path.Combine(System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "Area.xml");  
  5.             FileInfo fiXML = new FileInfo(_filePath);  
  6.             //如果文件不存在  
  7.             if (!(fiXML.Exists))  
  8.             {  
  9.                 XDocument xelLog = new XDocument(  
  10.                     new XDeclaration("1.0", "utf-8", "yes"),  
  11.                     new XComment("XML File For AREA"),  
  12.                     new XElement("Provinces",  
  13.                                  new XElement("Province", new XAttribute("Name", "省份"),  
  14.                                               new XElement("City", new XAttribute("Name", "城市"),  
  15.                                                            new XElement("District", new XAttribute("Name", "行政区")))  
  16.  
  17.                                      )  
  18.                         )  
  19.                     );  
  20.                 xelLog.Save(_filePath);  
  21.             }  
  22.         } 

这段代码使用指定的内容初始化 XDocument 类的新实例,然后调用XDocument的Save方法来生成一个XML文档。很少使用XDocument来创建XML树,通常是使用 XElement 根节点创建 XML 树。除非具有创建文档的具体要求(例如,必须在***创建处理指令和注释,或者必须支持文档类型),否则使用 XElement 作为根节点通常会更方便。运行这段代码,就会在生成的应用程序根目录下创建一个名为Area.xml的文档,文档内容如下:

  1. <?xml version="1.0" encoding="utf-8" standalone="yes"?> 
  2. <!--XML File For AREA--> 
  3. <Provinces> 
  4.   <Province Name="省份"> 
  5.     <City Name="城市"> 
  6.       <District Name="行政区" /> 
  7.     </City> 
  8.   </Province> 
  9. </Provinces> 

 

 

 

2)如何将一个XML树加载到程序内存。

我们操作一个XML文档首先是需要将该文档加载到程序的内存中,在LINQ to XML中,通常是使用XElement类型的Load方法将XML文档自根节点开始的XML树加载到一个XElement类型的对象中,然后我们就可以采用XElement提供的各种方法对这个内存中XML文档进行各种操作。

我们创建一个LINQtoXML的帮助类LinqToXmlHelper.cs,将对XML操作的相关方法都写在这个类里面,下面是一个加载XML文档到XElement对象的方法。

  1. /// <summary> 
  2.         /// 将Area.xml文档加载到内存中的XElement类型的对象xElement,成功调用 XElement.Load方法后会在xElement保存整棵XML树  
  3.         /// </summary> 
  4.         /// <returns></returns> 
  5.         public XElement Load()  
  6.         {  
  7.             XElement xElement = XElement.Load(_filePath);  
  8.             return xElement;  
  9.         } 

我们刚才已经创建了一个XML文档,现在我们将这个文档加载到内存中,然后打印这个XElement对象。

  1. static void Main(string[] args)  
  2.         {  
  3.             LinqToXmlHelper linqToXmlHelper = new LinqToXmlHelper();  
  4.             var elements = linqToXmlHelper.Load();  
  5.             string str = elements.ToString();  
  6.  
  7.             Console.WriteLine(str);  
  8.             Console.ReadKey();  

输出结果如下:

 

 

3)如何向现有的XML文档插入新的元素

到现在,我们已经了解了LINQ to XML中创建和加载XML文档的方式,接下来的问题就是如何向一个已经存在的XML文档添加新的节点。下面是增加新元素的方法,我们可以向Area.xml文档中添加新是省份城市和区域信息,如果已经存在的区域则进行更新,这里用XElement的Save对更改后的XML文档进行保存。

  1. /// <summary> 
  2.        /// 增加新元素,如果要增加的区已经存在,则对区的Description进行更新  
  3.        /// </summary> 
  4.        /// <param name="districts"></param> 
  5.        public void AddElement(IList<District> districts)  
  6.        {  
  7.            if(districts==null||districts.Count==0) return;  
  8.  
  9.            XElement xElement = Load();  
  10.            foreach (District district in districts)  
  11.            {  
  12.                if (district.City == null || district.City.Province == null)  
  13.                {  
  14.                    continue;  
  15.                }  
  16.                XElement provinceElement = xElement.Elements("Province").Where(e => ((string)e.Attribute("Name")).Equals(district.City.Province.Name)).FirstOrDefault();  
  17.               //判断该省份是否存在,不存在曾增加该省份的节点  
  18.                if(provinceElement==null)  
  19.                {  
  20.                     provinceElement = new XElement("Province", new XAttribute("Name", district.City.Province.Name), new XAttribute("Capital", district.City.Province.Capital));  
  21.                    xElement.Add(provinceElement);  
  22.                }  
  23.  
  24.                XElement cityElement = provinceElement.Elements("City").Where(e => ((string)e.Attribute("Name")).Equals(district.City.Name)).FirstOrDefault();  
  25.                //判断该城市是否存在,不存在则在对应省份下增加该城市的节点  
  26.                if(cityElement==null)  
  27.                {  
  28.                    cityElement = new XElement("City", new XAttribute("Name", district.City.Name), new XAttribute("Code", district.City.Code));  
  29.                    provinceElement.Add(cityElement);  
  30.                }  
  31.  
  32.                XElement districtElement = xElement.Elements("District").Where(e => ((string)e.Attribute("Name")).Equals(district.Name)).FirstOrDefault();  
  33.                //如果存在该区域的节点则先删除在添加,以这种方式更新节点  
  34.                if(districtElement!=null)  
  35.                {  
  36.                    districtElement.Remove();  
  37.                }  
  38.                districtElement = new XElement("District", new XAttribute("Name", district.Name), new XAttribute("Description", district.Description));  
  39.                cityElement.Add(districtElement);  
  40.  
  41.            }  
  42.           //操作完毕,将内存中的XML树保存回硬盘的XML文档中。  
  43.          xElement.Save(_filePath);  
  44.        } 

上面的AddElement方法中,调用XElement对象的传一个XElement对象的Add方法, 可以将一个XElement对象(节点)添加为一个已有节点的最后子节点。这样我们通过Add的方式就可以轻易扩展一个节点的子节点。

下面调用增加新元素AddElement方法,将一个区的集合信息保存到Area.xml文档中,然后打印XML树。代码如下:

  1. static void Main(string[] args)  
  2.         {  
  3.               
  4.             LinqToXmlHelper linqToXmlHelper = new LinqToXmlHelper();  
  5.             Province province = new Province() { Name = "广东省"Capital = "广州市" };  
  6.             City city = new City() { Name = "广州市"Code = "020"Province = province };  
  7.             IList<District> districts = new List<District>()  
  8.                                             { new District() {City = cityName = "天河区"Description = "天河区的描述"}, new District() {City = cityName = "越秀区"Description = "越秀区的描述"}  
  9.                                                   
  10.                                             };  
  11.             linqToXmlHelper.AddElement(districts);  
  12.             XElement xElement = linqToXmlHelper.Load();  
  13.             Console.WriteLine(xElement.ToString());  

输出结果如图:

 

 

4)如何查询和遍历XML文档的元素

根据XElement类型提供的Elements方法,我们可以获取某个节点的所有子节点元素,也可以通过传入节点名称为参数,获取某个节点下所有和参数节点名称相匹配的节点集合,可以根据XElement类型提供的Attibute方法获取某节点的属性信息,下面代码示例根据城市名查询该城市下所有的区的信息:

  1. /// <summary> 
  2.         /// 根据城市名查询该城市下所有的区的信息  
  3.         /// </summary> 
  4.         /// <param name="cityName"></param> 
  5.         /// <returns></returns> 
  6.         public IList<District> GetDistricts(string cityName)  
  7.         {  
  8.             IList<District> districts = new List<District>();  
  9.             XElement xElement = Load();  
  10.             //获取城市名为变量cityName的节点的所有子节点  
  11.             IEnumerable<XElement> xElementxElements =  
  12.                 xElement.Elements("Province").Elements().Where(e => ((string) e.Attribute("Name")).Equals(cityName)).Elements();  
  13.             foreach (XElement element in xElements)  
  14.             {  
  15.                 District district = new District();  
  16.                 district.Name = (string) element.Attribute("Name");  
  17.                 district.Description = (string) element.Attribute("Description");  
  18.                 districts.Add(district);  
  19.  
  20.             }  
  21.             return districts;  
  22.         } 

调用GetDistricts方法

  1. static void Main(string[] args)  
  2.         {  
  3.               
  4.             LinqToXmlHelper linqToXmlHelper = new LinqToXmlHelper();  
  5.             IList<District> districts = linqToXmlHelper.GetDistricts("广州市");  
  6.             foreach (var district in districts)  
  7.             {  
  8.                 Console.WriteLine(district.Name);  
  9.             }  
  10.           } 

输出结果为:

天河区

越秀区

5)如何删除XML文档中的节点元素

删除区的节点元素的方法,这里假定区的名称是唯一的

  1. /// <summary> 
  2.         /// 删除区的节点元素,这里假定区的名称是唯一的  
  3.         /// </summary> 
  4.         /// <param name="districts"></param> 
  5.         public void DeleteElement(IList<District> districts)  
  6.         {  
  7.             XElement xElement = Load();  
  8.             foreach (District district in districts)  
  9.             {  
  10.                  
  11.                 XElement districtElement = xElement.Elements("Province").Elements("City").Elements("District").Where(e => ((string)e.Attribute("Name")).Equals(district.Name)).FirstOrDefault();  
  12.                 if(districtElement!=null)  
  13.                 {  
  14.                     districtElement.Remove();  
  15.                 }  
  16.             }  
  17.             xElement.Save(_filePath);  
  18.  
  19.         } 

调用XElement.Remove方法可以在当前节点的父节点上删除当前节点。下面代码删除区节点中名称为“越秀区”的节点。

  1. static void Main(string[] args)  
  2.         {  
  3.               
  4.             LinqToXmlHelper linqToXmlHelper = new LinqToXmlHelper();  
  5.             IList<District> districts = new List<District>(){new District(){Name = "越秀区"} };  
  6.             linqToXmlHelper.DeleteElement(districts);  
  7.             XElement xElement = linqToXmlHelper.Load();  
  8.             Console.WriteLine(xElement.ToString());  
  9.             Console.ReadKey();  
  10.  
  11.         } 

输出结果为:

 

 

到这里,你已经看到了LINQ to XML技术操作XML最为常用一些功能,包括创建和加载XML文档,新增删除更新XML节点等。

原文:http://www.cnblogs.com/zoupeiyang/archive/2011/07/25/2115941.html

【编辑推荐】

  1. Linq to xml操作XML
  2. XML之父解读未来互联网"游戏化"的三个真谛
  3. Ajax和Web服务数据格式:XML SOAP HTML
  4. 超强解析XML——简单直接的来
  5. 解析PHP中的XML数据
责任编辑:陈贻新 来源: 边写边唱的博客
相关推荐

2011-07-26 13:58:17

LINQ

2011-07-22 08:43:08

XML

2022-08-19 07:13:45

SQL方法编程

2013-11-19 12:53:33

OA信息化

2023-10-15 12:18:36

MPLS网络

2009-09-17 13:54:26

LINQ to XML

2009-09-17 13:30:32

LINQ to XML

2009-01-04 16:58:48

LINQ to XMLLINQXML

2009-09-16 16:59:05

LINQ to XML

2009-09-14 16:41:23

LINQ To XML

2009-09-14 16:46:15

LINQ to XML

2009-09-16 16:52:50

LINQ to XML

2009-09-16 15:33:22

LINQ to XML

2009-09-14 15:12:40

LINQ to XML

2023-08-07 08:12:12

开源项目社区性质feature

2016-12-27 14:06:36

Python代码基础

2017-03-06 11:02:59

产品软件Power Desig

2009-09-08 17:45:13

Ophone Widg

2009-09-16 15:41:45

LINQ查询XML文档

2009-09-08 16:55:01

Linq实现XML转换
点赞
收藏

51CTO技术栈公众号