使用XPath查询带有命名空间(有xmlns)的XML(转)

最近碰到一个小问题,通过调用webservice返回如下的xml,
<Seller xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<id xmlns="http://www.aaa.com/">348388</id>
<gender xmlns="http://www.aaa.com/">Monsieur</gender>
<lastName xmlns="http://www.aaa.com/">FABRIZZI</lastName>
<firstName xmlns="http://www.aaa.com/">FRANCIS</firstName>
<login xmlns="http://www.aaa.com/">francis.fabrizzi@bayern-aix.net.bmw.fr</login>
<password xmlns="http://www.aaa.com/">KUVOTFP</password>
<profile xmlns="http://www.aaa.com/">Chef de vente</profile>
<email xmlns="http://www.aaa.com/">francis.fabrizzi@bayern-aix.net.bmw.fr</email>
<mobilePhone xmlns="http://www.aaa.com/">0600000000</mobilePhone>
<dateRec xmlns="http://www.aaa.com/">2012-02-21T22:49:49.283</dateRec>
<dateMod xmlns="http://www.aaa.com/">2012-02-21T22:49:49.283</dateMod>
<idDrv xmlns="http://www.aaa.com/">233734</idDrv>
<drv xmlns="http://www.aaa.com/">DAVID ROUSSEAU</drv>
<idCrv xmlns="http://www.aaa.com/">233775</idCrv>
<crv xmlns="http://www.aaa.com/">ALEXANDRA CORDIER</crv>
<idCdv xmlns="http://www.aaa.com/">0</idCdv>
<dealerCode xmlns="http://www.aaa.com/">FB001</dealerCode>
<dealerType xmlns="http://www.aaa.com/">Premium</dealerType>
<dealerQualification xmlns="http://www.aaa.com/">GOLD</dealerQualification>
<dealerName xmlns="http://www.aaa.com/">BAYERN AIX</dealerName>
<dealerAddress xmlns="http://www.aaa.com/">ZA La Pioline</dealerAddress>
<dealerZipCode xmlns="http://www.aaa.com/">13546</dealerZipCode>
<dealerCity xmlns="http://www.aaa.com/">AIX EN PROVENCE</dealerCity>
<dealerPhone1 xmlns="http://www.aaa.com/">0442162070</dealerPhone1>
<dealerPhone2 xmlns="http://www.aaa.com/">0442162089</dealerPhone2>
<dealerSellChannel xmlns="http://www.aaa.com/">CCP BMW Mini</dealerSellChannel>
</Seller>
当时也没有多想,直接用xpath解析了,没想到死活不成功,再仔细一看,原来有命名空间,真是头大。
然后去google找答案,如下部分转自帖子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在后面程序中也会用到)
<?xml version="1.0" encoding="utf-8"?>
<root xmlns="dotnet" xmlns:w="wpf">
<a>data in a</a>
<w:b>data in b</w:b>
<c xmlns="silverlight">
<w:d>
<e>data in e</e>
</w:d>
</c>
</root>
它的所有XML节点的命名空间如下所示:
<?xml version="1.0" encoding="utf-8"?>
<root xmlns="dotnet" xmlns:w="wpf">
<!-- xmlns: dotnet -->
<a>data in a</a>
<!-- xmlns: dotnet -->
<w:b>data in b</w:b>
<!-- xmlns: wpf -->
<c xmlns="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 = new XmlDocument();
xmlDoc.Load(@"C:\a.txt");
//加入命名空间和前缀
var xmlnsm = new XmlNamespaceManager(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
使用XPath查询带有命名空间(有xmlns)的XML(转)的更多相关文章
- .NET(C#):使用XPath查询带有命名空间(有xmlns)的XML
原文http://www.cnblogs.com/mgen/archive/2011/05/24/2056025.html 众所周知,XmlDocument可以进行XPath查询,但实际上这里所说的X ...
- 读写XML文档时,去掉新增加节点的“空命名空间”(xmlns=””)
在做对ReprotViewer编程时,想做一个用户可以更改显示/打印列的功能,大致看了下,只需要通过对rdlc文件中改变其<Hidden>节点值为false/true,即可实现对应某列的显 ...
- C#使用Linq to XML进行XPath查询
最近在用到HtmlAgliltyPack进行结点查询时,发现这里选择结点使用的是XPath.所以这里总结一下在C#中使用XPath查询XML的方法.习惯了用Linq,这里也是用的Linq to xml ...
- php解析带有命名空间的xml
xml如果带有命名空间我们将如何解析,例如: <ns1:CreateBillResponse xmlns:ns1="http://neusoft.com" xmlns:xsd ...
- 带有命名空间的xml解析,C#
前一段时间做花旗的接口,返回的xml格式是带有命名空间的,可是难倒了我,找了好久才找到解决办法,给大家分享下,少走弯路. 1,直接进入正题,先看一段带有命名空间的xml,这段xml大概的意思是,前面是 ...
- 让你编写的控件库在 XAML 中有一个统一的漂亮的命名空间(xmlns)和命名空间前缀
原文 让你编写的控件库在 XAML 中有一个统一的漂亮的命名空间(xmlns)和命名空间前缀 在 WPF XAML 中使用自己定义的控件时,想必大家都能在 XAML 中编写出这个控件的命名空间了.然而 ...
- Oracle查询一个命名空间下所有表和视图的表名、字段名、字段类型、字段大小,是否可为NULL,主键和注释信息
使用SQL查询Oracle一个命名空间下所有表和视图的表名.字段名.字段类型.字段大小,是否可为NULL,主键和注释信息. SQL如下,注意需要将'CDFLOOD'更换为您要查询的命名空间: sele ...
- MySQL 按照日期格式查询带有时间戳数据
按照日期格式查询带有时间戳数据一般在MSQL数据库中的时间都是以时间戳的格式来存储时间的,但是对于我们来说,时间戳格式具体表示的是什么时间,我们很难一眼看出来,所以当我们要具体查询某一个时间或时间段的 ...
- 2)thinkphp的带有命名空间的自动加载机制
(1)为啥thinkphp里面的文件要是写你的命名空间,要与你的路径一样,因为在thinkphp实现自动加载机制的原理,就是靠的你的命名空间对应这个路径,然后自动加载机制通过这个路径找到你的类文件,然 ...
随机推荐
- Python学习笔记(六)——类和对象
1.self的用法 全面理解self 2. 继承 子类继承父类,自动拥有父类的全部方法 >>> class Animal: def run(self): print('Animal ...
- Android开发 AAC的ADTS头解析[转载]
原文地址:https://www.jianshu.com/p/b5ca697535bd 1. ADTS(Audio Data Transport Stream)头之于AAC AAC音频文件的每一帧都由 ...
- CSIC_716_20191126【面向对象编程--继承】
继承 什么是继承:继承是新建类的一种方式,通过此方式生成的类称为子类.或者 派生类,被继承的类称为父类.基类或超类.在python中,一个子类可以继承多个父类. 继承的作用:减少代码的冗余,提高开发效 ...
- JVM之类加载过程
# 类的生命周期 1. 加载 loading2. 验证 verification3. 准备 preparation4. 解析 resoluation5. 初始化 initialization6. 使用 ...
- [JZOJ2866] 【集训队互测 2012】Bomb
题目 题目大意 给你一个有\(n\)个点的平面. 选择三个点,求两两之间曼哈顿距离和的最大值和最小值. 思考历程&正解 比赛的时候没有想太多,但感觉似乎比较水-- 首先有个很显然的性质,答案为 ...
- hdu6607 min25筛+杜教筛+伯努利数求k次方前缀和
推导过程类似https://www.cnblogs.com/acjiumeng/p/9742073.html 前面部分min25筛,后面部分杜教筛,预处理min25筛需要伯努利数 //#pragma ...
- csps-模拟7980题解
题面:https://www.cnblogs.com/Juve/articles/11712702.html 树: 我太sb了不知道DROT是1,还在sb找根 记录一个fa[]数组,表示x的祖先中第一 ...
- VS2008编译出现问题:error C2485: “__restrict”: 无法识别的扩展属性 解决办法
错误:Error3 error C2485: '__restrict' : unrecognized extended attribute f:\program files\microsoft vis ...
- Windbg 调试CPU占用过高
1.!runaway !runaway命令显示每个线程消费的时间 Bit 0 (0x1) 让调试器显示每个线程消耗的用户模式时间(user time),默认不加就是0x1 Bit 1 (0x2) 显示 ...
- 如何清除本机DNS缓存
如何清除本机DNS缓存 在实际应用过程中可能会遇到DNS解析错误的问题,就是说当我们访问一个域名时无法完成将其 解析到IP地址的工作,而直接输入网站IP却可以正常访问,这就是因为DNS解析出现故障造成 ...