C#中用SelectSingleNode方法解析带有多个命名空间的XML文件

 今晚在博问看到一个问题:查找xml文件中特定属性值的节点,给它增加一个新属性,本以为很简单,随手写了一个程序,却遇到了问题,主要是多个命名空间的原因,查找了一些资料最终解决了,现把解决的办法分享出来,大家如果有更好的方案欢迎留言讨论。

  XML文件如下:

<?xml version="1.0" encoding="utf-8" ?>
<Enginuity:ViewControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d
="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc
="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:Enginuity
="clr-namespace:Enginuity.Core;assembly=Enginuity.Core">
<Viewbox Stretch="Fill">
<TextBox Name="Text_10" Value="abc"/>
<TextBox Name="Text_11" Value="bcd"/>
</Viewbox>
</Enginuity:ViewControl>

  这里小小提示一下,Enginuity:ViewControl 这种写法表示ViewControl的命名空间为Enginuity。

  现在要得到的是Name为Text_10的TextBox结点的Value属性值:abc。

  关于SelectSingleNode方法大家可以参考:http://msdn.microsoft.com/en-us/library/h0hw012b.aspx

  这个方法有两个参数,第一个是string xpath,这个是必须的,第二个是XmlNamespaceManager nsmgr,这个可选。重要的一点就是xpath的写法,主要就是命名空间:节点/命名空间:节点/...,官方给的示例中只有一个命名空间,xml结构相对比较简单。

  从上面的XML文件中很容易看出ViewControl的命名空间是Enginuity,但ViewBox的命名空间是什么呢?查找了XML文件命名空间的定义后,发现有这么一句”如果Xml文档里没有明确指出当前节点的命名空间,那么当前节点的命名空间继承其父节点的命名空间“,ViewBox的父节点是ViewControl,ViewControl的命名空间是Enginuity,同时注意到Enginuity还不是最终的命名空间,Enginuity的命名空间是xmlns,那么是哪一个呢?

  动手试呗,于是写出下面的程序:

            XmlDocument dom = new XmlDocument();
dom.Load(
@"E:\NET\test.xml");
XmlNamespaceManager xnm
=new XmlNamespaceManager(dom.NameTable);
xnm.AddNamespace(
"e", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
xnm.AddNamespace(
"x", "http://schemas.microsoft.com/winfx/2006/xaml");
xnm.AddNamespace(
"d", "http://schemas.microsoft.com/expression/blend/2008");
xnm.AddNamespace(
"mc", "http://schemas.openxmlformats.org/markup-compatibility/2006");
xnm.AddNamespace(
"Enginuity", "clr-namespace:Enginuity.Core;assembly=Enginuity.Core");
XmlNodeList xNodes
= dom.SelectSingleNode("Enginuity:ViewControl", xnm).ChildNodes;
Console.WriteLine(xNodes[
0].NamespaceURI);

  结果如下:

C#中用SelectSingleNode方法解析带有多个命名空间的XML文件

  可以看到,ViewControl的命名空间为最顶及的xmlns,于是写出下面的程序:

            XmlDocument dom = new XmlDocument();
dom.Load(
@"E:\NET\test.xml");
XmlNamespaceManager xnm
=new XmlNamespaceManager(dom.NameTable);
xnm.AddNamespace(
"e", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
xnm.AddNamespace(
"x", "http://schemas.microsoft.com/winfx/2006/xaml");
xnm.AddNamespace(
"d", "http://schemas.microsoft.com/expression/blend/2008");
xnm.AddNamespace(
"mc", "http://schemas.openxmlformats.org/markup-compatibility/2006");
xnm.AddNamespace(
"Enginuity", "clr-namespace:Enginuity.Core;assembly=Enginuity.Core");
XmlNode xNode
= dom.SelectSingleNode("Enginuity:ViewControl/e:Viewbox/e:TextBox[@Name='Text_10']", xnm);
Console.WriteLine(xNode.Attributes[
"Value"].Value);

  运行后效果如下:

C#中用SelectSingleNode方法解析带有多个命名空间的XML文件

  期待中的”abc“终于出现了。

  因此,得出一个结论,在用SelectSingleNode方法解析含有多个命名空间的XML文件时,没有明确标出命名空间的节点,其命名空间为根节点的命名空间。如果还不确定可以从根节点开始,逐层输出该级节点的命名空间。

  keyword:SelectSingleNode,C#解析XML文件,SelectSingleNode多命名空间,



本文转自Artwl博客园博客,原文链接:http://www.cnblogs.com/artwl/,如需转载请自行联系原作者

上一篇:《深入解析IPv6(第3版)》——第1章 IPv6入门1.1 IPv4的局限


下一篇:Docker安装gitlab