1、LINQ to XML类
System.Xml.Linq命名空间含有19个类,下表列出了它们的名称及其描述:
类
|
描述
|
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
|
XNode 和 XAttribute 的抽象基类
|
XObjectChange
|
XObject引发事件时的事件类型
|
XObjectChangeEventArgs
|
为 Changing 和 Changed 事件提供数据
|
XProcessingInstruction
|
表示一个 XML 处理指令
|
XText
|
表示一个文本节点
|
以下的代码演示了如何使用LINQ to XML来快速创建一个xml:
public
static void CreateDocument()
{
XDocument xdoc = new XDocument
(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement("Root","root")
);
xdoc.Save(path);
}
|
运行该示例将会得到一个xml文件,其内容为:
<?
xml
version
=
"1.0"encoding="utf-8"standalone="yes"?>
<
Root
>
root</Root>
|
可以看出微软在LINQ上投入了很大的精力,使我们在编程时感觉到很舒服。下面将详细介绍处理XML时使用最多的三个类:XElement、XAttribute和XDocument。如果掌握了这些类,使用LINQ to XML时将会感到很顺手。
2、XElement类
XElement 类是 LINQ to XML 中的基础类之一。 它表示一个 XML 元素。 可以使用该类创建元素;更改元素内容;添加、更改或删除子元素;向元素中添加属性;或以文本格式序列化元素内容。 还可以与 System.Xml 中的其他类(例如 XmlReader、XmlWriter 和 XslCompiledTransform)进行互操作。
使用LINQ to XML创建xml文档有很多种方式,具体使用哪种方法要根据实际需要。而创建xml文档最简单、最常见的方式是使用XElement类。以下的代码演示了如何使用XElement类创建一个xml文档:
public
static void CreateCategories()
{
XElement root = new XElement("Categories",
new XElement("Category",
new XElement("CategoryID", Guid.NewGuid()),
new XElement("CategoryName", "Beverages")
),
new XElement("Category",
new XElement("CategoryID", Guid.NewGuid()),
new XElement("CategoryName", "Condiments")
),
new XElement("Category",
new XElement("CategoryID", Guid.NewGuid()),
new XElement("CategoryName", "Confections")
)
);
root.Save(path);
}
|
运行该示例将会得到一个xml文件,其内容为:
<?
xml
version
=
"1.0"encoding="utf-8"?>
<
Categories
>
<
Category
>
<
CategoryID
>
57485174-46fc-4e8c-8d98-d25b53d504a1</CategoryID>
<
CategoryName
>
Beverages</CategoryName>
</
Category
>
<
Category
>
<
CategoryID
>
1474dde1-8014-48f7-b093-b47ca5d5b770</CategoryID>
<
CategoryName
>
Condiments</CategoryName>
</
Category
>
<
Category
>
<
CategoryID
>
364224e0-e002-4939-90fc-0fd93e0cf35b</CategoryID>
<
CategoryName
>
Confections</CategoryName>
</
Category
>
</
Categories
>
|
LINQ to XML的强大之处还在于它可以使用LINQ to SQL或者LINQ to Object获取数据源,然后填充到xml树。以下的示例从Northwind数据库中读取Categories、Products表中的数据来创建包含产品类别,以及每个类别下所有产品的xml文件:
public
static void CreateCategoriesFromDatabase()
{
using (NorthwindDataContext db = new NorthwindDataContext())
{
XElement root = new XElement("Categories",
db.Categories
.Select
(
c => new XElement
(
"Category"
, new XElement("CategoryID", c.CategoryID)
, new XElement("CategoryName", c.CategoryName)
, new XElement
(
"Products"
, c.Products
.Select
(
p => new XElement
(
"Product"
, new XElement("ProductName", p.ProductName)
)
)
.Take(2)
)
)
)
.Take(3)
);
root.Save(path);
}
}
|
运行该示例将会得到一个xml文件,其内容为:
<?
xml
version
=
"1.0"encoding="utf-8"?>
<
Categories
>
<
Category
>
<
CategoryID
>
1</CategoryID>
<
CategoryName
>
Beverages</CategoryName>
<
Products
>
<
Product
>
<
ProductName
>
Chai</ProductName>
</
Product
>
<
Product
>
<
ProductName
>
Chang</ProductName>
</
Product
>
</
Products
>
</
Category
>
<
Category
>
<
CategoryID
>
2</CategoryID>
<
CategoryName
>
Condiments</CategoryName>
<
Products
>
<
Product
>
<
ProductName
>
Aniseed Syrup</ProductName>
</
Product
>
<
Product
>
<
ProductName
>
Chef Anton's Cajun Seasoning</ProductName>
</
Product
>
</
Products
>
</
Category
>
<
Category
>
<
CategoryID
>
3</CategoryID>
<
CategoryName
>
Confections</CategoryName>
<
Products
>
<
Product
>
<
ProductName
>
Pavlova</ProductName>
</
Product
>
<
Product
>
<
ProductName
>
Teatime Chocolate Biscuits</ProductName>
</
Product
>
</
Products
>
</
Category
>
</
Categories
>
|
XElement类包含了许多方法,这些方法使得处理xml变得轻而易举。有关这些方法请参照MSDN。
其中,Save、CreateReader、ToString和WriteTo方法是比较常用的三个方法:
方法
|
参数
|
返回值
|
描述
|
CreateReader
|
无
|
System.Xml.XmlReader
|
创建此节点的
XmlReader
|
Save
|
System.String
|
void
|
将此元素序列化为文件
|
System.IO.TextWriter
|
void
|
将此元素序列化为
TextWriter
| |
System.Xml.XmlWriter
|
void
|
将此元素序列化为
XmlWriter
| |
System.String,
System.Xml.Linq.SaveOptions
|
void
|
将此元素序列化为文件,并可以选择禁用格式设置
| |
System.IO.TextWriter,
System.Xml.Linq.SaveOptions
|
void
|
将此元素序列化为
TextWriter
,并可以选择禁用格式设置
| |
WriteTo
|
System.Xml.XmlWriter
|
void
|
将此元素写入
XmlWriter
|
ToString
|
无
|
System.String
|
返回此节点的缩进
XML
|
System.Xml.Linq.SaveOptions
|
System.String
|
返回此节点的
XML
,并可以选择禁用格式设置
|
现在有很多使用XmlReader作为数据源的应用程序,使用XElement可以很方便地提供支持。
3、XAttribute类
XAttribute类用来处理元素的属性,属性是与元素相关联的“名称-值”对,每个元素中不能有名称重复的属性。使用XAttribute类与使用XElement类的操作十分相似,下面的示例演示了如何在创建xml树时为其添加一个属性:
public
static XElement CreateCategoriesByXAttribute()
{
XElement root = new XElement("Categories",
new XElement("Category",
new XAttribute("CategoryID", Guid.NewGuid()),
new XElement("CategoryName", "Beverages")
),
new XElement("Category",
new XAttribute("CategoryID", Guid.NewGuid()),
new XElement("CategoryName", "Condiments")
),
new XElement("Category",
new XAttribute("CategoryID", Guid.NewGuid()),
new XElement("CategoryName", "Confections")
)
);
root.Save(path);
return root;
}
|
运行该示例将会得到一个xml文件,其内容为:
<?
xml
version
=
"1.0"encoding="utf-8"?>
<
Categories
>
<
Category
CategoryID
=
"a6d5ef04-3f83-4e00-aeaf-52444add7570">
<
CategoryName
>
Beverages</CategoryName>
</
Category
>
<
Category
CategoryID
=
"67a168d5-6b22-4d82-9bd4-67bec88c2ccb">
<
CategoryName
>
Condiments</CategoryName>
</
Category
>
<
Category
CategoryID
=
"17398f4e-5ef1-48da-8a72-1c54371b8e76">
<
CategoryName
>
Confections</CategoryName>
</
Category
>
</
Categories
>
|
XAttribute类的方法比较少,常用的三个是:
方法
|
描述
|
AddAnnotation
|
为该属性添加注解
|
Remove
|
删除该属性
|
SetValue
|
设定该属性的值
|
以下的示例使用Remove来删除第一个元素的CategoryID属性:
public
static void RemoveAttribute()
{
XElement xdoc = CreateCategoriesByXAttribute();
XAttribute xattr = xdoc.Element("Category").Attribute("CategoryID");
xattr.Remove();
xdoc.Save(path);
}
|
运行该示例将会得到一个xml文件,其内容为:
<?
xml
version
=
"1.0"encoding="utf-8"?>
<
Categories
>
<
Category
>
<
CategoryName
>
Beverages</CategoryName>
</
Category
>
<
Category
CategoryID
=
"5c311c1e-ede5-41e5-93f7-5d8b1d7a0346">
<
CategoryName
>
Condiments</CategoryName>
</
Category
>
<
Category
CategoryID
=
"bfde8db5-df84-4415-b297-cd04d8db9712">
<
CategoryName
>
Confections</CategoryName>
</
Category
>
</
Categories
>
|
作为尝试,试一试以下删除属性的方法:
public
static void RemoveAttributeByDoc()
{
XElement xdoc = CreateCategoriesByXAttribute();
XAttribute xattr = xdoc.Attribute("CategoryID");
xattr.Remove();
xdoc.Save(path);
}
|
运行该示例将会抛出一个空引用异常,因为元素Categories没有一个叫做CategoryID的属性。
4、XDocument类
XDocument类提供了处理xml文档的方法,包括声明、注释和处理指令。一个XDocument对象可以包含以下内容:
对象
|
个数
|
说明
|
XDeclaration
|
一个
|
用于指定xml声明中的重要组成部分,如文档编码和版本等
|
XElement
|
一个
|
指定文档的根元素
|
XDocumentType
|
一个
|
表示一个xml DTD
|
XComment
|
多个
|
Xml注释。它不能是第一个参数,因为一个有效的xml文档不能以注释作为开始
|
XProcessingInstruction
|
多个
|
为处理xml的应用程序指定任何所需信息
|
下面的示例创建了一个简单的xml文档,它包含几个元素和一个属性,以及一个处理指令和一些注释:
public
static void CreateXDocument()
{
XDocument xdoc = new XDocument(
new XProcessingInstruction("xml-stylesheet", "title='EmpInfo'"),
new XComment("some comments"),
new XElement("Root",
new XElement("Employees",
new XElement("Employee",
new XAttribute("id", "1"),
new XElement("Name", "Scott Klein"),
new XElement("Title", "Geek"),
new XElement("HireDate", "02/05/2007"),
new XElement("Gender", "M")
)
)
),
new XComment("more comments")
);
xdoc.Save(path);
}
|
运行该示例将会得到一个xml文件,其内容为:
<?
xml
version
=
"1.0"encoding="utf-8"?>
<?
xml-stylesheet
title='EmpInfo'
?>
<!--
some comments
-->
<
Root
>
<
Employees
>
<
Employee
id
=
"1">
<
Name
>
Scott Klein</Name>
<
Title
>
Geek</Title>
<
HireDate
>
02/05/2007</HireDate>
<
Gender
>
M</Gender>
</
Employee
>
</
Employees
>
</
Root
>
<!--
more comments
-->
|
XDocument类包含多个与XElement类相同的方法,具体内容可以参阅MSDN。需要注意的是,处理节点和元素的大部分功能都可以通过XElement获得,只有当绝对需要文档层次的处理能力,以及需要访问注释、处理指令和声明时,才有使用XDocument类的必要。
创建了xml文档后,可以使用NodesAfterSelf方法返回指定的XElement元素之后的所有同级元素。需要注意的是,此方法只包括返回集合中的同级元素,而不包括子代。此方法使用延迟执行。以下代码演示了这一过程:
public
static void NodesAfterSelf()
{
XElement root = new XElement("Categories",
new XElement("Category",
new XElement("CategoryID", Guid.NewGuid()),
new XElement("CategoryName", "
食品"
),
new XElement("Description", "
可以吃的东西"
)
)
);
foreach (var item in root.Element("Category").Element("CategoryID").NodesAfterSelf())
{
Console.WriteLine((item as XElement).Value);
}
}
|
执行的结果如下:
![](http://hi.csdn.net/attachment/201103/9/0_12996780138gb3.gif)
使用LINQ to XML中的类来处理xml十分简单和高效,包括创建、查询和操纵xml。
二、LINQ to XML编程概念
本节将介绍LINQ to XML编程的相关概念,例如如何加载xml、创建全新xml、操纵xml的信息以及遍历xml文档。
1、加载已有的xml
使用LINQ to XML加载xml可以从多种数据源获得,例如字符串、XmlReader、TextReader或文件。
下面的示例演示了如何从文件中加载xml:
public
static void LoadFromFile()
{
XElement root = XElement.Load(path);
Console.WriteLine(root.ToString());
}
|
也可以使用Parse方法从一个字符串加载xml:
public
static void LoadFromString()
{
XElement root = XElement.Parse(@"
<Categories>
<Category>
<CategoryID>1</CategoryID>
<CategoryName>Beverages</CategoryName>
<Description>Soft drinks, coffees, teas, beers, and ales</Description>
</Category>
</Categories>
"
);
Console.WriteLine(root.ToString());
}
|
2、保存xml
在前面的示例中曾多次调用XElement对象的Save方法来保存xml文档,在这里就不
冗述了。
3、创建xml
在前面的示例中曾多次调用XElement对象的构造函数来创建xml文档,在这里就不
冗述了。需要说明的是,在使用
LINQ to XML
创建
xml
文档时,会有代码缩进,这使代码的可读性大大加强。
4、遍历xml
使用LINQ to XML在xml树中遍历xml是相当简单的。只需要使用XElement和XAttribute类中所提供的方法。Elements和Element方法提供了定位到某个或某些元素的方式。下面的示例演示了如何遍历xml树,并获取指定元素的方式:
public
static void Enum()
{
XElement root = new XElement("Categories");
using (NorthwindDataContext db = new NorthwindDataContext())
{
root.Add(
db.Categories
.Select
(
c => new XElement
(
"Category"
, new XElement("CategoryName", c.CategoryName)
)
)
);
}
foreach (var item in root.Elements("Category"))
{
Console.WriteLine(item.Element("CategoryName").Value);
}
}
}
|
上述代码运行的结果为:
![](http://hi.csdn.net/attachment/201103/9/0_1299678028fBFt.gif)
是不是很简单呢?Nodes()、Elements()、Element(name)和Elements(name)方法为xml树的导航提供了基本功能。
5、操纵xml
LINQ to XML一个重要的特性是能够方便地修改xml树,如添加、删除、更新和复制xml文档的内容。
I.
插入
使用XNode类的插入方法可以方便地向xml树添加内容:
方法
|
说明
|
AddAfterSelf
|
紧跟在此节点之后添加指定的内容
|
AddBeforeSelf
|
紧邻此节点之前添加指定的内容
|
在下面的示例中,使用AddAfterSelf方法向现有xml中添加一个新节点:
public
static void AddAfterSelf()
{
XElement root = XElement.Parse(@"
<Categories>
<Category>
<CategoryID>1</CategoryID>
<CategoryName>Beverages</CategoryName>
<Description>Soft drinks, coffees, teas, beers, and ales</Description>
</Category>
</Categories>
"
);
XElement xele = root.Element("Category").Element("CategoryName");
xele.AddAfterSelf(new XElement("AddDate", DateTime.Now));
root.Save(path);
}
|
运行该示例将会得到一个xml文件,其内容为:
<?
xml
version
=
"1.0"encoding="utf-8"?>
<
Categories
>
<
Category
>
<
CategoryID
>
1</CategoryID>
<
CategoryName
>
Beverages</CategoryName>
<
AddDate
>
2010-01-31T03:08:51.813736+08:00</AddDate>
<
Description
>
Soft drinks, coffees, teas, beers, and ales</Description>
</
Category
>
</
Categories
>
|
当需要添加一个元素到指定节点之前时,可以使用AddBeforeSelf方法。
II.
更新
在LINQ to XML中更新xml内容可以使用以下几种方法:
方法
|
说明
|
ReplaceWith
|
用指定的内容来取代当前元素的内容
|
ReplaceAll
|
用指定的内容来取代当前元素的子节点及相关的属性
|
ReplaceNodes
|
用指定的内容来取代文档或当前元素的子节点
|
SetAttributeValue
|
设置属性的值、添加属性或移除属性
|
SetElementValue
|
设置子元素的值、添加子元素或移除子元素
|
在下面的示例中使用了ReplaceWith与SetElementValue方法对xml进行了更新操作:
public
static void Update()
{
XElement root = XElement.Parse(@"
<Categories>
<Category>
<CategoryID>1</CategoryID>
<CategoryName>Beverages</CategoryName>
<Description>Soft drinks, coffees, teas, beers, and ales</Description>
</Category>
</Categories>
"
);
root.Element("Category").Element("CategoryID").ReplaceWith(new XElement("ID", "2"));
root.Element("Category").SetElementValue("CategoryName", "test data");
root.Save(path);
}
|
运行该示例将会得到一个xml文件,其内容为:
<?
xml
version
=
"1.0"encoding="utf-8"?>
<
Categories
>
<
Category
>
<
ID
>
2</ID>
<
CategoryName
>
test data</CategoryName>
<
Description
>
Soft drinks, coffees, teas, beers, and ales</Description>
</
Category
>
</
Categories
>
|
III.
删除
可以使用Remove(XElement)与RemoveAll方法来删除xml。
在下面的示例中,使用了RemoveAll方法:
public
static void Remove()
{
XElement root = XElement.Parse(@"
<Categories>
<Category>
<CategoryID>1</CategoryID>
<CategoryName>Beverages</CategoryName>
<Description>Soft drinks, coffees, teas, beers, and ales</Description>
</Category>
</Categories>
"
);
root.RemoveAll();
root.Save(path);
}
|
运行该示例将会得到一个xml文件,其内容为:
<?
xml
version
=
"1.0"encoding="utf-8"?>
<
Categories
/>
|
在下面的示例中,使用了Remove方法删除了xml的Description元素:
public
static void Remove()
{
XElement root = XElement.Parse(@"
<Categories>
<Category>
<CategoryID>1</CategoryID>
<CategoryName>Beverages</CategoryName>
<Description>Soft drinks, coffees, teas, beers, and ales</Description>
</Category>
</Categories>
"
);
root.Element("Category").Element("Description").Remove();
root.Save(path);
}
|
运行该示例将会得到一个xml文件,其内容为:
<?
xml
version
=
"1.0"encoding="utf-8"?>
<
Categories
>
<
Category
>
<
CategoryID
>
1</CategoryID>
<
CategoryName
>
Beverages</CategoryName>
</
Category
>
</
Categories
>
|
6、处理属性
I.
添加
LINQ to XML添加属性与添加元素师类似的,可以使用构造函数或者Add方法来添加属性:
public
static void AddAttribute()
{
XElement root = new XElement("Categories",
new XElement("Category",
new XAttribute("CategoryID","1"),
new XElement("CategoryName","Beverages"),
new XElement("Description", "Soft drinks, coffees, teas, beers, and ales")
)
);
root.Element("Category").Add(new XAttribute("AddDate", DateTime.Now.ToShortDateString()));
root.Save(path);
}
|
运行该示例将会得到一个xml文件,其内容为:
<?
xml
version
=
"1.0"encoding="utf-8"?>
<
Categories
>
<
Category
CategoryID
=
"1"AddDate="2010-01-31">
<
CategoryName
>
Beverages</CategoryName>
<
Description
>
Soft drinks, coffees, teas, beers, and ales</Description>
</
Category
>
</
Categories
>
|
II.
检索
检索属性可以使用Attribute(name)方法:
public
static void SelectAttribute()
{
XElement root = new XElement("Categories",
new XElement("Category",
new XAttribute("CategoryID", "1"),
new XElement("CategoryName", "Beverages"),
new XElement("Description", "Soft drinks, coffees, teas, beers, and ales")
)
);
XAttribute xattr = root.Element("Category").Attribute("CategoryID");
Console.WriteLine(xattr.Name);
Console.WriteLine(xattr.Value);
}
|
上述代码的运行结果为:
CategoryID
1
|
III.
删除
删除属性的操作是调用XAttribute对象的Remove方法来完成的。
本文介绍了LINQ to XML的编程基础,即System.Xml.Linq命名空间中的多个LINQ to XML类,这些类都是LINQ to XML的支持类,它们使得处理xml比使用其他的xml工具容易得多。在本文中,着重介绍的是XElement、XAttribute和XDocument。