一、使用XML DOM的方式读取XML
本节要点:
- 加载XML的几种方式
- 读取没有Namespace的XML
- 使用XPath进行过滤,选出需要的节点
- 读取有Namespace的XML
XML DOM方式是最原始的一种操作XML的途径,从.Net Framework 1.0开始就开始支持DOM方式。
1. 如何用XML DOM的方式读取XML?
要读取XML首先要加载XML,加载的方式有两种,一种是从流或类似Reader加载,另一种就是加载字符串。
a. 从流或者Reader加载,Load方法有五个重载
XmlDocument doc = new XmlDocument(); doc.Load("D:\\Test.xml"); using (FileStream stream = File.OpenRead("D:\\Test.xml")) { doc.Load(stream); } using (TextReader reader = File.OpenText("D:\\Test.xml")) { doc.Load(reader); } using (XmlReader reader = XmlReader.Create("D:\\Test.xml")) { doc.Load(reader); }
b. 从字符串加载
XmlDocument doc = new XmlDocument(); doc.LoadXml(@"<?xml version=""1.0"" encoding=""UTf-16""?> <data> <item>abc</item> <item>123</item> <item>vwxyzh</item> </data>");
2. 读取无namespace的XML
XML已经准备好,下面就开始读取这个XML。
a. 现在希望读取data节下面所有item的text:
foreach (XmlElement item in doc.ChildNodes[1].ChildNodes) { Console.WriteLine(item.InnerText); }
结果:
abc
123
vwxyzh
b. 使用XPath进行过滤
上面的写法问题有很多,例如在data节点中有非item的节点,这样访问,也就被无差别的把非item项也写出来了。
例如:
<?xml version="1.0" encoding="UTf-8"?> <data> <item>abc</item> <item>123</item> <other>[email protected]#</other> <item>vwxyzh</item> </data>
结果:
abc
123
[email protected]#
vwxyzh
显然"[email protected]#"也被选择出来了,这不是我们所希望的,所以,改用XPath的方式访问:
foreach (XmlElement item in doc.SelectNodes("/data/item")) { Console.WriteLine(item.InnerText); }
结果:other项被排除在外了
abc
123
vwxyzh
3. 读取有namespace的XML
和C#一样XML也有namespace,并且namespace在XML中的作用巨大。
我们先来加载一个XML片段:
doc.LoadXml(@"<?xml version="1.0" encoding="UTf-8"?> <v:data xmlns:v="urn:vwxyzh"> <v:item>abc</v:item> <v:item>123</v:item> <v:other>[email protected]#</v:other> <v:item>vwxyzh</v:item> <v:item>2009/10/18</v:item> </v:data>");
这里我们准备了一个namespace—urn:vwxyzh,并缩写为v。
现在按照原来的XPath执行以下程序,会发现没有任何一个元素被选中。为什么会这样?
因为原来的"/data/item"中的data节是没有namespace的data,所以这个XPath根本定位不到任何节点。
必须要修改部分代码才能达到我们的目的,怎么办呢?
a. 先来看看SelectNodes方法有哪些重载吧:
public XmlNodeList SelectNodes(string xpath); public XmlNodeList SelectNodes(string xpath, XmlNamespaceManager nsmgr);
第一个重载就是之前使用的那个;
第二个重载,需要提供一个XmlNamespaceManager实例,一看名字就知道,这个实例是用来管理Xml的Namespace的。
b. 再来查看一下XmlNamespaceManager这个类,可以发现创建这个实例需要一个类型为XmlNameTable的实例做参数,那么谁能提供XmlNameTable的实例呢?
c. XmlDocument本身就提供了这个XmlNameTable:
d. 修改代码:
XmlNamespaceManager xnmgr = new XmlNamespaceManager(doc.NameTable); xnmgr.AddNamespace("v", "urn:vwxyzh"); foreach (XmlElement item in doc.SelectNodes("/v:data/v:item", xnmgr)) { Console.WriteLine(item.InnerText); }
先创建一个XmlNamespaceManager的实例,然后使用AddNamespace方法,把"v"设置为"urn:vwxyzh"。然后修改XPath,把dat修改为v:data,item修改为v:item,这样就可以了。
运行就可以看到结果为:
abc
123
vwxyzh
2009/10/18