C#操作xml SelectNodes,SelectSingleNode总是返回NULL 与 xPath 介绍

简介:

一. SelectNodes,SelectSingleNode总是返回NULL

   下面以一个简单的xml为例:

<?xml version="1.0"?> <message xmlns="http://www.mydomain.com/MyDataFeed" xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance 
AI 代码解读
xsi:schemaLocation="http://www.mydomain.com/MyDataFeed https://secure.mydomain/MyDataFeed/myDataFeed.xsd" 
AI 代码解读
requestId="13898" status="1"> <error>Invalid Login</error> </message>
AI 代码解读

     下面尝试读取error节点的内容

XmlNode errorNode = xmldoc.SelectSingleNode("/message/error"); if (errorNode != null) Console.Writeline("There is an error");
AI 代码解读

     返回的结果一直为Null

     产生这个问题的原因就在于上面的xml文档中使用了命名空间,当xml中定义了命名空间时,在查找节点的时候需要使用下面的方法

XmlNamespaceManager nsMgr = new XmlNamespaceManager(xmldoc.NameTable); nsMgr.AddNamespace("ns", "http://www.mydomain.com/MyDataFeed");
XmlNode errorNode = xmldoc.SelectSingleNode("/ns:message/ns:error", nsMgr);
AI 代码解读

    如果直接想定位到error,而不是从根开始,需要写为

xmldoc.SelectSingleNode("//ns:error", nsMgr); 
AI 代码解读

    感谢: http://stackoverflow.com/questions/1766254/selectsinglenode-always-returns-null

二 1. xPath介绍

   下面这个文章转载的太多了,已经不知道出处了…

XPath 是XML的查询语言,和SQL的角色很类似。以下面XML为例,介绍XPath 的语法。

<?xml version="1.0" encoding="ISO-8859-1"?>     

<catalog>     

  <cd country="USA">     

    <title>Empire Burlesque</title>     

    <artist>Bob Dylan</artist>     

    <price>10.90</price>    

  </cd>     

  <cd country="UK">     

    <title>Hide your heart</title>   

     <artist>Bonnie Tyler</artist>   

     <price>9.90</price>     

  </cd>     

  <cd country="USA">    

    <title>Greatest Hits</title>   

     <artist>Dolly Parton</artist>    

    <price>9.90</price>    

  </cd>   

</catalog>

定位节点

XML是树状结构,类似档案系统内数据夹的结构,XPath也类似档案系统的路径命名方式。不过XPath 是一种模式(Pattern),可以选出 XML档案中,路径符合某个模式的所有节点出来。例如要选catalog底下的cd中所有price元素可以用:

/catalog/cd/price

如果XPath的开头是一个斜线(/)代表这是绝对路径。如果开头是两个斜线(//)表示文件中所有符合模式的元素都会被选出来,即使是处于树中不同的层级也会被选出来。以下的语法会选出文件中所有叫做cd的元素(在树中的任何层级都会被选出来):

//cd

选择未知的元素

使用星号(Wildcards,*)可以选择未知的元素。下面这个语法会选出/catalog/cd 的所有子元素:

/catalog/cdprice

以下的语法会选出有两层父节点,叫做price的所有元素。

price

以下的语法会选择出文件中的所有元素。

//*

要注意的是,想要存取不分层级的元素,XPath语法必须以两个斜线开头(//),想要存取未知元素才用星号(*),星号只能代表未知名称的元素,不能代表未知层级的元素。

选择分支

使用中括号可以选择分支。以下的语法从catalog的子元素中取出第一个叫做cd的元素。XPath的定义中没有第0元素这种东西。

/catalog/cd[1]

以下语法选择catalog中的最后一个cd元素:(XPathj并没有定义 first() 这种函式喔,用上例的 [1]就可以取出第一个元素。

/catalog/cd[last()]

以下语法选出含有price子元素的所有/catalog/cd元素。

/catalog/cd[price]

以下语法选出price元素的值等于10.90的所有/catalog/cd元素

/catalog/cd[price=10.90]

以下语法选出price元素的值等于10.90的所有/catalog/cd元素 的price元素

/catalog/cd[price=10.90]/price

选择一个以上的路径

使用Or操作数(|)就可以选择一个以上的路径。例如:

/catalog/cd/title | catalog/cd/artist

选择所有title以及artist元素

//title | //artist

选择所有title以及artist以及price元素

//title | //artist | //price

选择属性

在XPath中,除了选择元素以外,也可以选择属性。属性都是以@开头。例如选择文件中所有叫做country的属性:

//@country

选择所有含有country这个属性的cd元素:

//cd[@country]

以下语法选择出含有属性的所有cd元素

//cd[@*]

以下语法选择出country属性值为UK的cd元素

//cd[@country='UK']

只要掌握了xpath语法,理论上你就可以访问xml文件中的任意节点和任意值

XmlNode xmlnode = xmldoc.SelectSingleNode("//document/section[@id='pla-01']/data[@id='fou_scc_code']");

 

 

 

 

2、[译]XPath和CSS选择器

原文:http://ejohn.org/blog/xpath-css-selectors


最近,我做了很多工作来实现一个同时支持XPath和CSS 3的解析器,令我惊讶的是:它们俩在某些方面上非常相似,而在另一些方面上又完全不同.不同的地方有,CSS是用来配合HTML工作的,可以使用#id来根据ID获取元素,以及使用.class来根据class获取元素.这些用XPath实现的话都不会那么简洁,反过来呢,XPath可以使用..来返回到DOM树的上层节点中,还可以使用foo[bar]来获取到一个拥有bar子元素的foo元素.CSS选择器完全做不到这些,总结一下就是,和XPath比起来,CSS选择器通常都比较短小,但可惜的是不够强大.

我认为将这两种选择器的写法做一个比较是很有价值的.

目标 CSS 3 XPath
所有元素 * //*
所有的P元素 p //p
所有的p元素的子元素 p > * //p/*
根据ID获取元素 #foo //*[@id='foo']
根据Class获取元素 .foo                                //*[contains(@class,'foo')] 1
拥有某个属性的元素 *[title] //*[@title]
所有P元素的第一个子元素 p > *:first-child //p/*[0]

所有拥有子元素a的P元素

无法实现 //p[a]
下一个兄弟元素 p + * //p/following-sibling::*[0]

从语法上看,我非常惊讶这两种选择器在某些情况下的相似性,尤其是'>'和'/'两者之间.虽然他们并不总是有着相同的功能(XPath中要取决于正在使用的轴),但通常情况下他们指的都是某个父元素的子元素.还有,空白符' '和'//'都意味着当前元素的所有后代元素.最后是星号'*',类似于通配符,表示所有元素,而不管是哪种标签名.


1 这个写法其实不正确,因为它不光会匹配到我们想要的'foo bar',还会意外的匹配到'foobar'.正确的写法可能会非常复杂,可能会需要用到多个表达式才能完成.

下面是译者注:

上表中错误的XPath:
//*[contains(@class,'foo')]
我实现的写法是:
//*[@class='foo' or contains(@class,' foo ') or starts-with(@class,'foo ') or substring(@class,string-length(@class)-3)=' foo']

比起CSS的.foo,真的是好复杂,我来解释一下,一个元素的class属性中如果包含'foo',可能有四种情况,列出表来是这样的:

class="foo" //*[@class='foo'] class属性只有一个值foo
class="foobar foo bar" //*[@class=' foo '] class属性值中,foo在其他两边的值的中间

class="foo bar"

//*[starts-with(@class,'foo ')] class属性值中,foo在最左边
class="bar foo" //*[substring(@class,string-length(@class)-3)=' foo'] class属性值中,foo在最右边,XPath1.0中没有ends-with函数,2.0有,现在浏览器实现的都是1.0

那么我们能在网页开发中用上XPath吗?最初,jQuery是支持XPath选择器的,但后来,由于效率问题,jQuery放弃了对XPath的支持.刚好,谷歌在上个月发布了Wicked Good XPath,这是一个DOM Level 3 XPath规范的纯JavaScript实现,也是目前同类实现中最快的,我们可以把这个脚本和jQuery结合起来使用.

复制代码
jQuery.getScript("http://wicked-good-xpath.googlecode.com/files/wgxpath.install.js").success(function () {    //加载库文件
wgxpath.install(); //安装XPath支持
jQuery.xpath = function (xpath) { var elements = []; //用来存储XPath选择到的元素
var xpathResult = document.evaluate(xpath, document, null, 6, null); for (var i = 0; i < xpathResult.snapshotLength; i++) { elements.push(xpathResult.snapshotItem(i)); } return jQuery(elements); //传给jQuery工厂方法,返回jQuery对象
} })
复制代码

这样就能通过.xpath(),jQuery,使()没什么差别.本页面已经加载了这个脚本,你可以现在打开控制台试验一下$.xpath方法.

那我们有了CSS选择器,为什么还要用XPath呢,答案是:有些时候,XPath更强大一点.比如:

在上面John Resig总结的表中,有一个CSS无法实现的功能,就是查找包含某个子元素的父元素.的确,目前的CSS还无法实现,不过在未来CSS4的选择器中,将会有一个父选择器

E! > F    //注意,2011年的时候,父选择器的语法是$E > F,今年草案又改了.网上有些介绍CSS4选择器的博文还是旧的,这里有一个能在CSS文件中使用父选择器的polyfill https://github.com/Idered/cssParentSelector
AI 代码解读

该选择器可以选取到那些包含子元素F的E元素.但即便以后实现了CSS4,稍微改变一下需求,查找那些包含后代元素F的E元素,CSS选择器又怎么写呢?应该是没什么办法实现.熟悉jQuery的朋友可能会说,jQuery里有:has伪类,可以这么写E:has(F),的确,如果使用jQuery自定义的过滤器,几乎任何需求都可以用遍历DOM的方法实现,但效率绝对会很低.而XPath就不一样了,毕竟Firefox和chrome都已经实现了XPath的接口document.evaluate方法(Wicked Good XPath应该主要是努力在IE上实现统一的接口),速度肯定比手动遍历DOM来的快.XPath的写法是这样的//E[.//F],怎么样,也挺简单明了的.

另外很重要的一点是,CSS本来是用于给HTML添加样式的,12种节点类型中,只有元素节点(nodetype等于1)才有样式这一说,因此,CSS选择器只能选取到页面中的元素节点,而XPath就不是了,它不光可以用在HTML中,还可以用在XML中,除了元素节点,而可以选择属性节点(//@*)或者文本节点(//text())等,如果未来XPath2.0实现了,它会变的更加强大.

 

下文是对C#对XML的具体操作

如何完成.Net下XML文档的读写操作

C#操作xml SelectNodes,SelectSingleNode总是返回NULL 与 xPath 介绍

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

原文地址



本文转自Work Hard Work Smart博客园博客,原文链接:http://www.cnblogs.com/linlf03/archive/2011/11/30/2268705.html,如需转载请自行联系原作者

目录
打赏
0
0
0
0
51
分享
相关文章
|
7月前
|
C# 中的 XML 与 JSON 数据处理
在现代软件开发中,数据交换和存储需求日益增长,XML 和 JSON 成为最常用的数据格式。本文从 C# 角度出发,详细介绍如何处理这两种格式,并提供示例代码。对于 XML,我们介绍了读取、创建和写入 XML 文件的方法;对于 JSON,则展示了如何使用 Newtonsoft.Json 库进行数据解析和序列化。此外,文章还总结了常见问题及其解决方案,帮助开发者更好地应对实际项目中的挑战。
258 61
C# 中的 XML 与 JSON 数据处理
Spring5系列学习文章分享---第一篇(概述+特点+IOC原理+IOC并操作之bean的XML管理操作)
Spring5系列学习文章分享---第一篇(概述+特点+IOC原理+IOC并操作之bean的XML管理操作)
66 1
|
6月前
|
C#使用XML文件的详解及示例
C#使用XML文件的详解及示例
240 0
C#使用HttpClient四种请求数据格式:json、表单数据、文件上传、xml格式
C#使用HttpClient四种请求数据格式:json、表单数据、文件上传、xml格式
1169 0
C#中的WebClient与XPath:实现精准高效的Screen Scraping
Screen Scraping是自动化提取网页数据的技术。C#的WebClient结合XPath能高效精准抓取信息。WebClient负责HTTP请求,XPath则精确定位HTML数据。为应对反爬措施,可通过代理IP、定制user-agent与cookie及多线程增强爬虫性能。示例代码展示了设置代理、头信息及多线程抓取澎湃新闻网页标题的过程。
C#中的WebClient与XPath:实现精准高效的Screen Scraping
|
11月前
|
C# xml文档反序列化记事
本文介绍了使用XmlSerializer进行XML序列化和反序列化的关键点。包括:1) 以独占方式读取XML文件以避免并发问题;2) 当元素名与类型名不一致时,可通过`[XmlArrayItem]`指定元素名,或创建继承自原始类型的子类;3) 处理DateTime反序列化错误,通过中间字符串属性转换;4) 提到了常用C#特性如`[XmlRoot]`, `[XmlElement]`, `[XmlAttribute]`, `[XmlIgnore]`和`[XmlArrayItem]`的作用。
实时计算 Flink版操作报错合集之使用 Event Time Temporal Join 关联多个 HBase 后,Kafka 数据的某个字段变为 null 是什么原因导致的
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
233 0
实时计算 Flink版操作报错合集之使用 Event Time Temporal Join 关联多个 HBase 后,Kafka 数据的某个字段变为 null 是什么原因导致的
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
143 0
|
11月前
|
c#XML、JSON的序列化和反序列化,看完你就懂了
c#XML、JSON的序列化和反序列化,看完你就懂了
304 0
|
5月前
|
C# 一分钟浅谈:Code Contracts 与契约编程
【10月更文挑战第26天】本文介绍了 C# 中的 Code Contracts,这是一个强大的工具,用于通过契约编程增强代码的健壮性和可维护性。文章从基本概念入手,详细讲解了前置条件、后置条件和对象不变量的使用方法,并通过具体代码示例进行了说明。同时,文章还探讨了常见的问题和易错点,如忘记启用静态检查、过度依赖契约和性能影响,并提供了相应的解决建议。希望读者能通过本文更好地理解和应用 Code Contracts。
86 3

热门文章

最新文章

相关课程

更多
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等