27.2 使用DOM
W3C的文档对象模型(Document Object Model,DOM)是一个使程序和脚本有能力动态地访问和更新文档的内容、结构以及样式的接口,与平台和语言无关。DOM被分为3种类型,如下所示。
❑核心DOM:用于任何结构化文档的标准模型;
❑XML DOM:用于XML文档的标准模型;
❑HTML DOM:用于HTML文档的标准模型。
本章要使用的就是XML DOM,因为我们要操作的文档类型是XML。这里要详细讨论的也是XML DOM,它是用于获取、更改、添加或删除XML元素的标准。XML文档中的每个组成部分都是一个节点。
DOM是这样规定的:
❑整个文档是一个文档节点;
❑每个XML标签是一个元素节点;
❑包含在XML元素中的文本是文本节点;
❑每一个XML属性是一个属性节点;
❑注释属于注释节点。
下面是一个示例XML文档,如代码清单27-1所示。
代码清单27-1 示例XML文档
<?xml version="1.0"encoding="UTF-8"?>
<books>
<book category=“计算机”>
<title lang=“中文”>C Sharp 4.0程序设计</title>
<author>姜晓东</author>
<year>2010</year>
</book>
<book category=“小说”>
<title lang=“英文”>哈利波特与魔法石</title>
<author>J K.Rowling</author>
<year>1977</year>
</book>
</books>
如果使用图形表示,上述XML代码可以用图27-1表示,注意,这里仅包含了一个<book>节点。
图 27-1 DOM树
接下来,我们使用这些类来对代码清单27-1的XML文档进行节点和属性的增删改查处理,以了解XML文档的基本操作。将上述XML文档保存于c:\books.xml,如果下文没有说明,均指该xml文档。具体代码如代码清单27-2所示。
代码清单27-2 对XML文档元素进行增删改查
using System;
using System.Xml;
namespace ProgrammingCSharp4
{
class XmlHandleSample
{
public static void Main()
{
try
{
//声明一个XmlDocument对象,代表xml文档
XmlDocument doc=new XmlDocument();
//通过路径将xml文档的内容加载到doc对象中
doc.Load(@"c:\books.xml");
//使用xpath表达式查询出books节点,它是根节点
XmlNode root=doc.SelectSingleNode("books");
//声明并初始化一个新的XmlElement对象,表示book节点
XmlElement newBookNode=doc.CreateElement("book");
//为book节点创建一个名为category的属性,并赋值
newBookNode.SetAttribute("category",“计算机”);
//创建一个名为title的节点,它是book节点的子节点
XmlElement newTitleNode=doc.CreateElement("title");
//为title节点指定文字内容
newTitleNode.InnerText=“计算机程序设计艺术(第一卷,第三版)”;
//为title子节点新增属性,并赋值
newTitleNode.SetAttribute("lang",“英文”);
//将title节点添加到book节点
newBookNode.AppendChild(newTitleNode);
//和新增title节点类似,此处省略
XmlElement newAuthorNode=doc.CreateElement("author");
newAuthorNode.InnerText=“高德纳”;
newBookNode.AppendChild(newAuthorNode);
XmlElement newYearNode=doc.CreateElement("year");
newYearNode.InnerText="1997";
newBookNode.AppendChild(newYearNode);
//将新增的book节点添加到根节点
root.AppendChild(newBookNode);
//保存新的xml文档到新文件
doc.Save(@"c:\books2.xml");
Console.WriteLine(“新增节点成功完成。”);
Console.WriteLine(“任意键继续修改一个节点……”);
Console.ReadKey();
//重新初始化doc对象
doc=new XmlDocument();
//并加载books2.xml,这是新增了一个节点的xml文档
doc.Load(@"c:\books2.xml");
//使用xpath,查询出具有category属性,且值
//为“计算机”的book节点,返回一个XmlNodeList集合对象
XmlNodeList nodes=doc.SelectNodes(“//book[@category='计算机']”);
//遍历返回的节点集合
foreach(XmlNode node in nodes)
{
XmlElement current=(XmlElement)node;
//修改属性值
current.SetAttribute("category","computer");
XmlElement author=current.SelectSingleNode("author")as XmlElement;
//修改节点的值
if(author.InnerText.Equals(“姜晓东”))
{
author.InnerText="Jiang Xiao Dong";
}
else if(author.InnerText.Equals(“高德纳”))
{
author.InnerText="Donald Ervin Knuth";
}
}
doc.Save(@"c:\books3.xml");
Console.WriteLine(“修改节点成功完成。”);
Console.WriteLine(“任意键继续删除一个节点……”);
Console.ReadKey();
doc=new XmlDocument();
doc.Load(@"c:\books3.xml");
//查询出新增的节点
XmlNode bookNode=doc.SelectSingleNode("//book[author='Donald Ervin Knuth']");
//移除当前节点
bookNode.ParentNode.RemoveChild(bookNode);
doc.Save(@"c:\books4.xml");
Console.WriteLine(“删除节点成功完成。”);
Console.WriteLine(“任意键退出……”);
Console.ReadKey();
}
catch(System.Exception)
{
Console.WriteLine(“处理过程出错,请检查。”);
throw;
}
}
}
}
上述代码运行结果为:
新增节点成功完成。
任意键继续修改一个节点……
修改节点成功完成。
任意键继续删除一个节点……
删除节点成功完成。
任意键退出……
代码清单27-2 先在代码清单27-1所示的XML文档的基础上新增了一个book节点,并另存为c:\books2.xml,其内容如代码清单27-3所示。
代码清单27-3 books2.xml
然后重新加载books2.xml文档,将“category=‘计算机’”的book节点查找出来。这里使用的是xpath查询表达式,可见查询的结果将会有两个book节点。然后将这些book节点的category的属性值改为computer,并将各自的中文作者名修改为英文,最终修改结果保存为c:\books3.xml,其内容如代码清单27-4所示。
代码清单27-4 books3.xml
最后,以books3.xml为基础,将开始新增的book节点删除掉,并把结果保存为c:\books4.xml。其内容如代码清单27-5所示。
代码清单27-5 books4.xml
<?xml version="1.0"encoding="UTF-8"?>
<books>
<book category="computer">
<title lang=“中文”>C Sharp 4.0程序设计</title>
<author>Jiang Xiao Dong</author>
<year>2010</year>
</book>
<book category=“小说”>
<title lang=“英文”>哈利波特与魔法石</title>
<author>J K.Rowling</author>
<year>1977</year>
</book>
</books>