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 ...
随机推荐
- 使用 ActiveMQ 实现JMS 异步调用
目录 简介 启动 ActiveMQ 服务器 查看控制台 ActiveMQ 的消息通道 Queue Topic 比较 开发生产者和消费者 开发服务端(消费者) 开发客户端(生产者) 参考 简介 服务之间 ...
- hdu1072(Nightmare)bfs
Nightmare Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total ...
- 一些减少代码量、提高开发效率的利器(Java)
Spring Boot mybatis-plus代码生成器和自带CRUD接口 lombok 库: Apache Commons & guava AOP Java8: stream & ...
- cf250D. The Child and Sequence(线段树 均摊复杂度)
题意 题目链接 单点修改,区间mod,区间和 Sol 如果x > mod ,那么 x % mod < x / 2 证明: 即得易见平凡, 仿照上例显然, 留作习题答案略, 读者自证不难. ...
- 比较完整的PeopleSoft工具表名
因为找不到其他地方有相对完整的PeopleSoft表名,因为我自己总结了一份. 在这里尝试提供一个庞大的PeopleSoft表列表,以便当你想快速访问PeopleSoft工具表时候,可以快速的查看这篇 ...
- matlab练习程序(异或分类)
clear all; close all; clc; %生成两组已标记数据 randn(); mu1=[ ]; S1=[; 0.5]; P1=mvnrnd(mu1,S1,); mu2=[ ]; S2= ...
- Python 数据分析基础小结
一.数据读取 1.读写数据库数据 读取函数: pandas.read_sql_table(table_name, con, schema=None, index_col=None, coerce_fl ...
- textbox只允许输入数字
private void txtUserId_KeyPress(object sender, KeyPressEventArgs e) { //如果输入的不是数字键,也不是回车键.Backspace键 ...
- HDFS namenode 写edit log原理以及源码分析
这篇分析一下namenode 写edit log的过程. 关于namenode日志,集群做了如下配置 <property> <name>dfs.nameservices< ...
- Azure 中虚拟机的计划内维护
Azure 定期执行更新,以提高虚拟机的主机基础结构的可靠性.性能及安全性. 此类更新包括修补宿主环境(例如操作系统.虚拟机监控程序以及主机上部署的各种代理)中的软件组件.升级网络组件以及硬件解除授权 ...