XML 读写(XmlDocument、XPathNavigator、XDocument)
内存中的 XML 处理
基于流的 XML 处理提供了最小的负载,但也只提供了最小的灵活性。在很多 XML 处理场景里,你不会在这么低的层次下工作。
对内存中的 XML 的处理则更加方便,但没有单一、标准的方式。如下所有的类都支持对 XML 的读取和导航:
- XmlDocument :它是 XML 数据的标准化接口,但对时间要求比较多。
- XPathNavigator :它提供比 XML DOM 稍快、更有效的模型,并增强了一些搜索功能,但不能修改或保存 XML 。
- XDocument :为处理 XML 提供一个更直观和有效的 API。从技术上讲,它是 LINQ to XML 的一部分,但即使没有 LINQ 查询,它也很有用。
XmlDocument
XmlDocument 把信息保存为树的节点。节点是 XML 文件的基本组成部分,它可以使一个元素、特性、注释或者元素的一个值。
为了挖掘树的所有层次,下面这个示例使用了递归来操作 XmlDocument 类:
protected void Page_Load(object sender, EventArgs e)
{
string xmlFile = Server.MapPath("DvdList.xml");
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile); // doc.LoadXml() 可以接收一个XML格式的字符串
string str = GetChildNodesDescr(doc.ChildNodes, );
Response.Write(str);
} private string GetChildNodesDescr(XmlNodeList nodeList, int level)
{
string indent = "";
for (int i = ; i < level; i++)
{
indent += "";
} StringBuilder str = new StringBuilder();
foreach (XmlNode node in nodeList)
{
switch (node.NodeType)
{
case XmlNodeType.Comment:
str.Append(indent);
str.Append("Comment: <b>");
str.Append(node.Value).Append("</b><br />");
break;
case XmlNodeType.Element:
str.Append(indent);
str.Append("Element: <b>").Append(node.Name).Append("</b><br />");
break;
case XmlNodeType.Text:
str.Append(indent);
str.Append(" - Value: <b>");
str.Append(node.Value).Append("</b><br />");
break;
case XmlNodeType.XmlDeclaration:
str.Append("XML Declaration: <b>").Append(node.Name);
str.Append(" ").Append(node.Value).Append("</b><br />");
break;
} if (node.Attributes != null)
{
foreach (XmlAttribute attribute in node.Attributes)
{
str.Append(indent).Append(" - Attribute: <b>");
str.Append(attribute.Name).Append("</b> - Value: <b>");
str.Append(attribute.Value).Append("</b><br />");
}
} if (node.HasChildNodes) // node.ChildNodes.Count != 0
{
// level 作为递归传递的变量,进入新方法后自然会递增
// 因此这里一定不能用 (level++) 或 ++level 否则排版会乱
str.Append(GetChildNodesDescr(node.ChildNodes, level+));
}
}
return str.ToString();
}

并非所有类型的节点都同时具备名称和值。例如,对于元素 Title,它的名字就是 Title,不过它的值为空,因为它的值被保存到随后的 Text 节点中了。
XPathNavigator
XPathNavigator 类(在 System.Xml.XPath 命名空间里)和 XmlDocument 类的工作方式很相似。它把所有信息都加载到内存中并允许你在节点中移动。关键的区别是它使用基于游标的方式允许你使用 MoveToNext()之类的方法在 XML 数据间移动。每次 XPathNavigator 类只能定位到一个节点。
可以使用 XmlDocument.CreateNavigator()方法从 XmlDocument 创建一个 XPathNavigator。
下面是一个示例:
protected void Page_Load(object sender, EventArgs e)
{
string xmlFile = Server.MapPath("DvdList.xml");
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile); XPathNavigator xnav = doc.CreateNavigator();
Response.Write(GetXNavDescr(xnav, ));
} // xnav 是定位在某一个节点上的游标,而不是节点的集合
private string GetXNavDescr(XPathNavigator xnav, int level)
{
string indent = "";
for (int i = ; i < level; i++)
{
indent += " ";
} StringBuilder str = new StringBuilder();
switch (xnav.NodeType)
{
case XPathNodeType.Comment:
str.Append(indent);
str.Append("Comment: <b>").Append(xnav.Value);
str.Append("</b><br />");
break;
case XPathNodeType.Element:
str.Append(indent);
str.Append("Element: <b>").Append(xnav.Name);
str.Append("</b><br />");
break;
case XPathNodeType.Root:
str.Append("<b>Root</b><br />");
break;
case XPathNodeType.Text:
str.Append(indent);
str.Append(" - Value: <b>").Append(xnav.Value);
str.Append("</b><br />");
break;
} if (xnav.HasAttributes)
{
xnav.MoveToFirstAttribute();
do
{
str.Append(indent);
str.Append(" - Attribute: <b>").Append(xnav.Name);
str.Append("</b> Value: <b>").Append(xnav.Value);
str.Append("</b><br />");
} while (xnav.MoveToNextAttribute());
xnav.MoveToParent();
} if (xnav.HasChildren)
{
xnav.MoveToFirstChild();
do
{
str.Append(GetXNavDescr(xnav, level + ));
} while (xnav.MoveToNext());
xnav.MoveToParent();
}
return str.ToString();
}
效果和上个示例一样。代码中两处 xnav.MoveToParent()是必须的,因为操作的是节点的游标,递归时传递的游标也只有一个,里层处理完不返回上一层的话,外层方法循环的条件里无法正确处理游标,导致数据丢失。
XDocument
XDocument 是管理内存中 XML 所有功能的模型!与 XmlDocument 和 XPathNavigator 不同,它擅长构建 XML 内容。XmlDocument 使 XML 构建不必太复杂,而 XPathNavigator 则完全不支持。
如果要以非线性的方式生成 XML ,例如需要把一系列元素写入根元素,然后又要在这些元素里添加更多的信息,就必须使用 XDocument 这样的内存类。
与 XmlDocument 非常相似,但有一个区别,在 LINQ to XML 模型里,特性没有被看做单独的节点而是被看做附加到其他元素的 名称/值 对。
从技术层面而言,XDocument 是 LINQ 的一部分。它在 System.Xml.Linq 命名空间里,并且它是 .NET 3.5 中 System.Xml.Linq 程序集的一部分,使用这个类需要添加对该程序集的引用。
1. 使用 XDocument 创建 XML
通过 XDocument 可以使用整洁和精确的代码生成 XML 内容,用 XElement 类还可以创建一个不表示完整的 XML 内容。
所有的 LINQ to XML 类都提供了有用的构造函数,它允许在同一步里对其创建和初始化:
XElement element = new XElement("Price", "23.99");
保存的代码甚至变得更加疯狂,它们能够在一行代码里创建嵌套的节点树。这两个类(XDocument、XElement)包含最后一个接收参数数组(params)的构造函数。这个参数数组包含一套嵌套的节点。
下面的示例创建一个有两个嵌入元素以及它们内容的元素:
XElement element = new XElement("Starring",
new XElement("Star", "Tom Hanks"),
new XElement("Star", "Robin Wright")
);
扩展上述的技术,我们创建一个完整的 XML 文档,包括全部的元素、文本内容、特性、注释:
private void WriteXmlWithXDocument()
{
XDocument doc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XComment("Created: " + DateTime.Now.ToString()),
new XElement("DvdList",
new XElement("DVD",
new XAttribute("ID", ""),
new XAttribute("Category", "Science Fiction"),
new XElement("Title", "The Matrix"),
new XElement("Director", "Larry Wachowski"),
new XElement("Price", "18.74"),
new XElement("Starring",
new XElement("Star", "Keanu Reeves"),
new XElement("Star", "Laurence Fishburne")
)
), new XElement("DVD",
new XAttribute("ID", ""),
new XAttribute("Category", "Drama"),
new XElement("Title", "Forrest Gump"),
new XElement("Director", "Robert Zemeckis"),
new XElement("Price", "23.99"),
new XElement("Starring",
new XElement("Star", "Tom Hanks"),
new XElement("Star", "Robin Wright")
)
), new XElement("DVD",
new XAttribute("ID", ""),
new XAttribute("Category", "Horror"),
new XElement("Title", "The Others"),
new XElement("Director", "Alejandro Amenábar"),
new XElement("Price", "22.49"),
new XElement("Starring",
new XElement("Star", "Nicole Kidman"),
new XElement("Star", "Cristopher Eccleston")
)
), new XElement("DVD",
new XAttribute("ID", ""),
new XAttribute("Category", "Mystery"),
new XElement("Title", "Mulholland Drive"),
new XElement("Director", "David Lynch"),
new XElement("Price", "25.74"),
new XElement("Starring",
new XElement("Star", "Laura Harring")
)
), new XElement("DVD",
new XAttribute("ID", ""),
new XAttribute("Category", "Science Fiction"),
new XElement("Title", "A.I. Artificial Intelligence"),
new XElement("Director", "Steven Spielberg"),
new XElement("Price", "23.99"),
new XElement("Starring",
new XElement("Star", "Haley Joel Osment"),
new XElement("Star", "Jude Law")
)
)
)
); doc.Save(Server.MapPath("DvdList.xml"));
}
这段代码的作用和以前介绍的 XmlTextWrite 代码的作用完全相同,但是它更短,更容易阅读。它也比创建内存中的 XmlDocument 的等效代码更简单!另外,这样书写的代码通过语句精确的缩进反映了 XML 元素的嵌套关系,这让你迅速知道 XML 文档的整体形状。
结论:
创建 XML 文档的首选操作类就是 XDocument 。
2. 使用 XDocument 读取流
XDocument 还可以简化对 XML 内容的读取和导航,得到一个含有内容的 XDocument 之后,可以使用 XElement 类的主要属性和方法深入节点树。
- XDocument.Load():从文件、URI 或流中读取 XML 文档
- XDocument.Parse():从一个字符串加载 XML 文档
XElement 类的核心方法:
| Attributes() | 获取这个元素的 Attribute 对象的集合 |
| Attribute() | 获取特定名称的 Attribute |
| Elements() | 获取第一层的子 XElement 元素,或者你可以指定元素的名称。 |
| Element() | 获取由该元素包含的具有指定名称的 XElement ,如果没有匹配的就返回空值 |
| Nodes() | 获取该元素包含的所有 XNode 对象,这包括元素以及其他内容,如注释 |
请注意 XDocument 和 XmlDocument 一个很重要的区别。XDocument 嵌套的元素通过方法而不是属性来暴露,这让你能够过滤出你感兴趣的那部分元素,当然,你也可以获取所有元素。
XDocument 类(以及其他 LINQ to XML 类)通常提供更多的成员:
- 节点成员(FirstNode、LastNode、NextNode、PreviousNode、Parent)
- 检查是否有孩子(HasElements)、特性(HasAttributes)、内容(IsEmpty)
- 插入、移除等其他操作( Add()、AddAfterSelf()AddBeforeSelf()、RemoveNodes()、Remove()、ReplaceWith()等)
LINQ to XML 的另一个简化是它不要求你区分元素和其中的文本,它们在 XML DOM 里由两个单独的节点表示。你可以通过把他转换为相应的数据类型得到内部的值:
string title = (string)titleElement;
Decimal price = (Decimal)decimalElement;
设置元素内的文本内容同样简单,只要把新值赋给 Value 属性:
priceElement = (decimal)priceElement * ;
下面这段直观的代码重写之前的 XPathNavigator 的 XML 处理代码。它扫描可用的元素,并把标题、导演以及价格信息添加到列表里:
private string ReadXML()
{
string xmlFile = Server.MapPath("DvdList.xml");
XDocument doc = XDocument.Load(xmlFile); StringBuilder str = new StringBuilder();
foreach (XElement element in doc.Element("DvdList").Elements())
{
// element.Element("Title").ToString() 出来的格式是
// <Title>......</Title>,因此取值只能使用下面的转换
str.Append("<ul><b>");
str.Append((string)element.Element("Title"));
str.Append("</b><li>");
str.Append((string)element.Element("Director"));
str.Append("</li><li>");
str.Append(string.Format("{0:C}", (decimal)element.Element("Price")));
str.Append("</li></ul>");
}
return str.ToString();
}
3. 命名空间
XDocument 类以特别优雅的方式处理命名空间。只要定义一个 XNameSpace 对象,然后使用它作为名称的一部分创建 XElement 元素即可:
XNamespace ns = "http://www.somecompany.com/DvdList";
XDocument doc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XComment("Created: " + DateTime.Now.ToString()),
new XElement(ns + "DvdList",
new XElement(ns + "DVD",
new XAttribute("ID", ""),
new XAttribute("Category", "Science Fiction"),
new XElement(ns + "Title", "The Matrix"),
new XElement(ns + "Director", "Larry Wachowski"),
new XElement(ns + "Price", "18.74"),
new XElement(ns + "Starring",
new XElement(ns + "Star", "Keanu Reeves"),
new XElement(ns + "Star", "Laurence Fishburne")
)
)
)
......
);
所有元素被放到了新的 XML 命名空间,但特性没有,因为特性已经是附加到元素的了,所以没必要特别再把特性放到同一个命名空间里。
如果元素在 XML 命名空间里,对 XML 文档进行遍历的时候必须同时考虑命名空间:
XNamespace ns = "http://www.somecompany.com/DvdList";
string title = (string)element.Element(ns + "Title");
XML 读写(XmlDocument、XPathNavigator、XDocument)的更多相关文章
- C# -- 使用XmlDocument或XDocument创建xml文件
使用XmlDocument或XDocument创建xml文件 需引用:System.Xml; System.Xml.Linq; 1.使用XmlDocument创建xml(入门案例) static vo ...
- 七、Linq To XML:XElement、XDocument
一.概述 LINQ to XMLLINQ to XML 是一种启用了 LINQ 的内存 XML 编程接口,使用它,可以在 .NET Framework.NET Framework 编程语言中处理 XM ...
- XmlDocument,XDocument相互转换
XmlDocument,XDocument相互转换 using System; using System.Xml; using System.Xml.Linq; namespace MyTest { ...
- 【Python】Python XML 读写
class ACTIVE_FILE_PROTECT_RULE_VIEW(APIView): renderer_classes = (JSONRenderer, BrowsableAPIRenderer ...
- XML读写工具
import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import j ...
- C# XML技术总结之XDocument 和XmlDocument
引言 虽然现在Json在我们的数据交换中越来越成熟,但XML格式的数据还有很重要的地位. C#中对XML的处理也不断优化,那么我们如何选择XML的这几款处理类 XmlReader,XDocument ...
- 通俗易懂,C#如何安全、高效地玩转任何种类的内存之Span的脾气秉性(二)。 异步委托 微信小程序支付证书及SSL证书使用 SqlServer无备份下误删数据恢复 把list集合的内容写入到Xml中,通过XmlDocument方式写入Xml文件中 通过XDocument方式把List写入Xml文件
通俗易懂,C#如何安全.高效地玩转任何种类的内存之Span的脾气秉性(二). 前言 读完上篇<通俗易懂,C#如何安全.高效地玩转任何种类的内存之Span的本质(一).>,相信大家对sp ...
- XML技术总结之XDocument 和XmlDocument
引言 虽然现在Json在我们的数据交换中越来越成熟,但XML格式的数据还有很重要的地位. C#中对XML的处理也不断优化,那么我们如何选择XML的这几款处理类 XmlReader,XDocument ...
- 网站的配置文件XML读写
网站的配置信息一般都写入到XML中,以下是简单的对xml的读写操作,仅供参考. 读操作: XmlDocument xmlDoc = new XmlDocument(); XmlReaderSettin ...
随机推荐
- Tomcat Connector原理
Tomcat工作原理 要了解其中的工作原理我们首先看如下两个图 Tomcat基本架构图: Tomcat请求示意图: 客户端的请求通过Connector接受处理后在到容器Engine->Host- ...
- 超强、超详细Redis入门教程
(1)什么是redis? Redis 是一个基于内存的高性能key-value数据库. (有空再补充,有理解错误或不足欢迎指正) (2)Reids的特点 Redis本质上是一个Key-Value类型的 ...
- Python数据模型
引言 像大多数人一样,我在对一直传统的面向过程语言C一知半解之后,走进了面向对象的世界,尽管对OOP一无所知,还好Python还保留有函数式编程,这使得我才不那么抵触,直到现在,习惯了面向对象之后,也 ...
- [bug]解决chrome浏览器不支持所有媒体音乐不自动播放问题
声音无法自动播放这个在 IOS/Android 上面一直是个惯例,桌面版的 Safari 在 2017 年的 11 版本也宣布禁掉带有声音的多媒体自动播放功能,紧接着在 2018 年 4 月份发布的 ...
- img,a,锚链接,超链接
1.图片标签:img,单标签 图片属性: src(source): 图片的来源(路径),可以放置本地图片,也可以放网上的图片的url地址 title: 当鼠标停留在图片上的时候,显示提示的文字 alt ...
- java中System.currentTimeMillis()
System.curentTimeMillis();会产生一个当前的毫秒. 1.计算某个方法的耗时 long curTime = System.currentTimeMillis(); resourc ...
- flutter tab切换页面防止重置
问题描述:TabBar 配合TabBarView切换页面,然后每个页面是一个listview加载数据,但是切换页面后listview的数据会被重置, 重新被加载了,解决办法使用 with Automa ...
- Android之编写测试用例
测试是软件工程中一个非常重要的环节,而测试用例又可以显著地提高测试的效率和准确性.测试用例其实就是一段普通的程序代码,通常是带有期望的运行结果的,测试者可以根据最终的运行结果来判断程序是否能正常工作. ...
- Python网络爬虫笔记(四):使用selenium获取动态加载的内容
(一) 说明 上一篇只能下载一页的数据,第2.3.4....100页的数据没法获取,在上一篇的基础上修改了下,使用selenium去获取所有页的href属性值. 使用selenium去模拟浏览器有点 ...
- 学习git踩坑之路
第一次使用git: 1.使用CentOS Linux release 7.3.1611 (Core),内核版本3.10.0-514.el7.x86_64 2.安装git: root权限运行:yum ...