.NET(C#):使用XPath查询带有命名空间(有xmlns)的XML

简介: 原文 http://www.cnblogs.com/mgen/archive/2011/05/24/2056025.html 众所周知,XmlDocument可以进行XPath查询,但实际上这里所说的XPath查询仅限于没有命名空间(没有xmlns属性)的XML,一旦遇到有命名空间的XML,对应XPath查询都会无结果。

原文 http://www.cnblogs.com/mgen/archive/2011/05/24/2056025.html

众所周知,XmlDocument可以进行XPath查询,但实际上这里所说的XPath查询仅限于没有命名空间(没有xmlns属性)的XML,一旦遇到有命名空间的XML,对应XPath查询都会无结果。

比如下面这个XML

<a xmlns="mgen.cnblogs.com">

    <b>ccc</b>

</a>

XPath查询/a/b会返回null,而如果没有xmlns的话,会返回节点b。

 

为什么会这样呢?MSDN的相应函数有解释(参考:http://msdn.microsoft.com/en-us/library/system.xml.xmlnode.selectsinglenode.aspx

If the XPath expression does not include a prefix, it is assumed that the namespace URI is the empty namespace. If your XML includes a default namespace, you must still add a prefix and namespace URI to the XmlNamespaceManager; otherwise, you will not get any nodes selected.

 

意思就是如果XPath表达式没有加前缀(如a:b中前缀是a),那么所查询节点(注意属性也可以是节点)的命名空间URI就应该是空值(也是默认值),否则XPath不会返回结果。

上面的XML, 因为节点a和b都有命名空间值,自然XPath查询不会有结果。

(上面英文还提到如果节点有默认命名空间,那么还得手动向XmlNamespaceManager添加前缀和命名空间值,这个在后面会讲的)

 

在看解决方案前,首先需要能够辨识XML命名空间,当然辨识XML命名空间值还是很容易的,参考如下XML(这个XML在后面程序中也会用到)

<?xmlversion="1.0" encoding="utf-8"?>

<rootxmlns="dotnet" xmlns:w="wpf">

  <a>data in a</a>               

  <w:b>data in b</w:b>        

  <cxmlns="silverlight">

    <w:d>                            

      <e>data in e</e>             

    </w:d>

  </c>

</root>

 

它的所有XML节点的命名空间如下所示:

<?xmlversion="1.0" encoding="utf-8"?>

<rootxmlns="dotnet" xmlns:w="wpf">

  <!-- xmlns: dotnet -->

  <a>data in a</a>

  <!-- xmlns: dotnet -->

  <w:b>data in b</w:b>

  <!-- xmlns: wpf -->

  <cxmlns="silverlight">

    <!-- xmlns: silverlight -->

    <w:d>

      <!-- xmlns: wpf -->

      <e>data in e</e>

      <!-- xmlns: silverlight -->

    </w:d>

  </c>

</root>

如果识别XML命名空间没有问题,那么后面的操作就相当简单了,你需要记住:在XmlDocument中用XPath查询某一节点时,只要它的命名空间值不是空值,那么你必须给它一个前缀, 用这个前缀代表这个节点的命名空间值!这些前缀是通过XmlNamespaceManager类添加的,使用时将XmlNamespaceManager 传入SelectNodes或SelectSingleNode中即可。这也是为什么上面说“如果节点有默认命名空间,那么还得手动向 XmlNamespaceManager添加前缀和命名空间值”的原因。

 

另外构造一个XmlNamespaceManager需要XmlNameTable对象,这个对象可以从XmlDocument.NameTable和XmlReader.NameTable属性中得到。

 

下面我们步入代码,比如说查询上面XML中的节点e,分析位置节点e位于:root->c->d->e,然后将所需命名空间值加入到XmlNamespaceManager中(前缀名称无所谓,只要在XPath一致即可),查询即可成功,如下代码:

/*

* 假设上面XML文件在C:\a.txt中

* 下面代码会查询目标节点e,并输出数据:data in e

* */

 

var xmlDoc =newXmlDocument();

xmlDoc.Load(@"C:\a.txt");

 

//加入命名空间和前缀

var xmlnsm =newXmlNamespaceManager(xmlDoc.NameTable);

xmlnsm.AddNamespace("d", "dotnet");

xmlnsm.AddNamespace("s", "silverlight");

xmlnsm.AddNamespace("w", "wpf");

 

var node = xmlDoc.SelectSingleNode("/d:root/s:c/w:d/s:e", xmlnsm);

Console.WriteLine(node.InnerText);

 

//输出:data in e

目录
相关文章
|
24天前
|
Java 物联网 C#
C#/.NET/.NET Core学习路线集合,学习不迷路!
C#/.NET/.NET Core学习路线集合,学习不迷路!
|
28天前
|
Java 物联网 编译器
C#一分钟浅谈:.NET Core 与 .NET 5 区别
本文对比了 .NET Core 和 .NET 5,从历史背景、主要区别、常见问题及易错点等方面进行了详细分析。.NET Core 侧重跨平台支持和高性能,而 .NET 5 在此基础上统一了 .NET 生态系统,增加了更多新特性和优化。开发者可根据具体需求选择合适的版本。
45 7
|
24天前
|
人工智能 开发框架 前端开发
C#/.NET/.NET Core技术前沿周刊 | 第 12 期(2024年11.01-11.10)
C#/.NET/.NET Core技术前沿周刊 | 第 12 期(2024年11.01-11.10)
|
24天前
|
开发框架 网络协议 .NET
C#/.NET/.NET Core优秀项目和框架2024年10月简报
C#/.NET/.NET Core优秀项目和框架2024年10月简报
|
1月前
|
XML 数据格式 开发者
XML 命名空间
XML 命名空间
|
23天前
|
人工智能 开发框架 安全
C#/.NET/.NET Core技术前沿周刊 | 第 13 期(2024年11.11-11.17)
C#/.NET/.NET Core技术前沿周刊 | 第 13 期(2024年11.11-11.17)
|
24天前
|
网络协议 Unix Linux
精选2款C#/.NET开源且功能强大的网络通信框架
精选2款C#/.NET开源且功能强大的网络通信框架
|
24天前
|
程序员 C# 图形学
全面的C#/.NET自学入门指南
全面的C#/.NET自学入门指南
|
2月前
|
JSON C# 开发者
C#语言新特性深度剖析:提升你的.NET开发效率
【10月更文挑战第15天】C#语言凭借其强大的功能和易用性深受开发者喜爱。随着.NET平台的演进,C#不断引入新特性,如C# 7.0的模式匹配和C# 8.0的异步流,显著提升了开发效率和代码可维护性。本文将深入探讨这些新特性,助力开发者在.NET开发中更高效地利用它们。
37 1
|
2月前
|
存储 消息中间件 NoSQL
Redis 入门 - C#.NET Core客户端库六种选择
Redis 入门 - C#.NET Core客户端库六种选择
66 8