XPath 是 XML 路径语言(XML Path Language),用来确定XML文档中某部分位置的语言。无论是什么语言什么框架,几乎都可以使用 XPath 来高效查询 XML 文件。

本文将介绍 .NET 中的 XPath 相关类型的使用。


本文读写的 XML 文件会以 文章末尾的代码 - 假设的 XML 文件 作为示例。

关于 XPath 语法,可以阅读 XML 的 XPath 语法 了解更多。

 

一切从这里开始

.NET 中支持 XPath 的 XML 文档类有两种读取方法,一种是 XPathDocument,以只读的方式读取;另一种是 XmlDocument,不止可以读,还可以编辑。

// 得到 walterlv.xml 文档在内存中的快速只读表示形式。
var xPathDocument = new XPathDocument("walterlv.xml");
// 以可读可写的方式打开 walterlv.xml 文件。
var xmlDocument = new XmlDocument();
xmlDocument.Load("walterlv.xml");

如果要确定 XML 的文件编码,需要使用 XmlTextReader 来读 XML 文件;它的基类 XmlReader 没有提供编码信息。XmlTextReader 作为参数传入 XPathDocument 的构造函数或 XmlDocument.Load 方法中即可。

无论是 XPathDocument 还是 XmlDocument,因为都实现了 IXPathNavigable,所以都有 CreateNavigator(); 方法,调用能得到 XPathNavigator 对象。不过前者的 CanEditfalse,后者的 CanEdittrue

var navigator1 = xPathDocument.CreateNavigator();
var navigator2 = xmlDocument.CreateNavigator();

上手 XPath

路径查询

XPathNavigator 对象提供了下面两种通用的 XPath 表达式的使用检索方法。

  • Select
  • SelectSingleNode

比如希望检索本文末尾的 XML 文件中的 id,使用 /package/metadata/id 即可检索。

当然,事实上这个 XML 文件是不能这样检索出来 id 的,因为它带有命名空间。

带有命名空间的检索需要使用到 XmlNamespaceManager 类,并写成下面这样:

var namespaceManager = new XmlNamespaceManager(new NameTable());
namespaceManager.AddNamespace("d", "http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd");
navigator.Select("/d:package/d:metadata/d:id", namespaceManager);

这里其实略微奇怪,因为命名 packageid 等都在默认的命名空间下,我们却必须显式加一个命名空间前缀。微软对此的解释是如果不指定命名空间前缀,默认都是 null,而不是 XML 声明的那个默认命名空间。这里是原文

XPath treats the empty prefix as the null namespace. In other words, only prefixes mapped to namespaces can be used in XPath queries. This means that if you want to query against a namespace in an XML document, even if it is the default namespace, you need to define a prefix for it.

路径检索的语法也有很多种,可以参考我的另一篇文章 XML 的 XPath 语法

为了提升性能,XPathNavigator 额外提供了这些方法,用于替代 XPath 中的部分对应的语法:

  • SelectChildren
  • SelectAncestors
  • SelectDescendants

XPath 函数调用

CompileEvaluate 提供了复杂的 XPath 函数调用。比如下面我们把几种 url 都拼接在一起得到一个新字符串。

XPathExpression query = navigator.Compile("concat(//licenseUrl/text(), //projectUrl/text(), //iconUrl/text())");
string urls = (string) navigator.Evaluate(query);

节点匹配

Matches 用来检查当前的节点是否满足某个条件。比如下面的例子便是检查当前节点的父节点是否是 group 并且其 targetFramework 属性为 .NETStandard2.0。显然,符合这个条件的只有最后的那个 dependency 节点。

navigator.Matches("../group/@targetFramework='.NETStandard2.0'");

XPath 导航

XPathNavigator 可以在节点、属性中间移动,以便能够不止从根节点进行查询。

  • MoveTo
  • MoveToChild
  • MoveToFirst
  • MoveToFirstChild
  • MoveToFollowing
  • MoveToId
  • MoveToNext
  • MoveToParent
  • MoveToPrevious
  • MoveToRoo
  • MoveToAttribute
  • MoveToFirstAttribute
  • MoveToNextAttribute
  • MoveToNamespace
  • MoveToFirstNamespace
  • MoveToNextNamespace

在导航到需要的节点或者属性后,可以使用 navigator.OuterXml 拿到节点的所有 XML 字符串。也可以使用下面这些方法拿到节点内部的值。

  • ValueAsBoolean
  • ValueAsDateTime
  • ValueAsDouble
  • ValueAsInt
  • ValueAsLong
  • ValueAs

编辑 XML

由于我们要编辑 XML 数据,所以加载 XML 文件的方式不能是 XPathDocument 了,得是 XmlDocument

插入使用 Insert 相关的方法,删除使用 Delete 相关的方法。而修改数据使用 SetValue

保存 XML 到文件

保存 XML 使用 XmlDocumentSave 或者 WriteTo 方法即可。


假设的 XML 文件

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
<metadata>
<id>MSTestEnhancer</id>
<version>1.6.0</version>
<authors>walterlv</authors>
<owners>walterlv</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<licenseUrl>https://github.com/easiwin/MSTestEnhancer/blob/master/LICENSE</licenseUrl>
<projectUrl>https://easiwin.github.io/mstest-enhancer</projectUrl>
<iconUrl>https://easiwin.github.io/mstest-enhancer/icon.png</iconUrl>
<description>MSTestEnhancer helps you to write unit tests without naming any method. You can write method contract descriptions instead of writing confusing test method name when writing unit tests.</description>
<releaseNotes>Support passing null into WithArgument method.</releaseNotes>
<copyright>Copyright (c) 2018 dotnet职业技术学院</copyright>
<repository type="git" url="https://github.com/easiwin/MSTestEnhancer.git" />
<dependencies>
<group targetFramework=".NETFramework4.5">
<dependency id="MSTest.TestFramework" version="1.2.0" exclude="Build,Analyzers" />
<dependency id="System.ValueTuple" version="4.4.0" exclude="Build,Analyzers" />
</group>
<group targetFramework=".NETFramework4.7">
<dependency id="MSTest.TestFramework" version="1.2.0" exclude="Build,Analyzers" />
</group>
<group targetFramework=".NETStandard2.0">
<dependency id="MSTest.TestFramework" version="1.2.0" exclude="Build,Analyzers" />
</group>
</dependencies>
</metadata>
</package>

参考资料

.NET 使用 XPath 来读写 XML 文件的更多相关文章

  1. C#读写xml文件的常用方法

    已知有一个XML文件(bookshop.xml)如下: <?xml version="1.0" encoding="gb2312" ?> <b ...

  2. PHP读写XML文件的四种方法

    PHP对XML文件进行读写操作的方法一共有四种,分别是:字符串方式直接读写.DOMDocument读写. XMLWrite写和XMLReader读.SimpleXML读写,本文将依次对这四种方法进行介 ...

  3. Java 读写XML文件 API--org.dom4j

    om4j是一个Java的XML API,类似于jdom,用来读写XML文件的.dom4j是一个十分优秀的JavaXML API,具有性能优异.功能强大和极其易使用的特点,同时它也是一个开放源代码的软件 ...

  4. Fixflow引擎解析(三)(模型) - 创建EMF模型来读写XML文件

    Fixflow引擎解析(四)(模型) - 通过EMF扩展BPMN2.0元素 Fixflow引擎解析(三)(模型) - 创建EMF模型来读写XML文件 Fixflow引擎解析(二)(模型) - BPMN ...

  5. cocos2d-x 读写 xml 文件

    cocos2d-x 读写 xml 文件 A product of cheungmine使用cocos2d-x开发2d游戏确实方便,但是对于一般的小游戏,经常需要的工作是UI布局设计和调整,代码改来改去 ...

  6. 使用XPath对象解析xml文件

    使用XPath对象解析xml文件 1.DocumentBuilderFactory类  工厂API,使应用程序能从XML文档获取生成DOM对象树的解析器 其构造方法受保护,用newInstance() ...

  7. java通过dom读写xml文件

    java通过dom读写xml文件 要读的xml文件 <?xml version="1.0" encoding="GB2312"?><学生花名册 ...

  8. PowerShell技巧:使用XPath语法查询XML文件

    [TechTarget中国原创] XML是存储结构化数据的一个很好的途径,但是想要让数据在其中发挥作用又会有些困难.每一种语言都有其特定方式来查询XML文件中的命名空间.元素及属性.PowerShel ...

  9. C# 读写XML文件的方法

    C# 读写XML文件的方法 一.写XML文件 XmlDocument xmlDocument = new XmlDocument();xmlDocument.AppendChild(xmlDocume ...

随机推荐

  1. shell脚本中case select 的使用

    #!/bin/bash # case echo "1.Install PHP" echo "2.Install Mysql" echo "3.Inst ...

  2. 简化Kubernetes应用部署工具-Helm

    [编者的话]微服务和容器化给复杂应用部署与管理带来了极大的挑战.Helm是目前Kubernetes服务编排领域的唯一开源子项目,做为Kubernetes应用的一个包管理工具,可理解为Kubernete ...

  3. mac 下测试各种IE版本

    背景 作为前端开发,在谈到兼容性时不得不谈到IE浏览器,那么,如果在mac上该怎么测试各种版本的IE呢 方法 1. 下载VirtualBox虚拟器 2. 下载安装了对应版本的windows系统,htt ...

  4. iOS 可变字符串NSMutableString的使用

    .创建一个可变字符串 NSMutableString * ms1 = [[NSMutableString alloc]init]; .可以通过类方法来创建 NSMutableString * ms2 ...

  5. 【Jmeter】压测mysql数据库中间件mycat

    背景 因为博主所负责测试的项目需要数据库有较大的吞吐量,在最近进行了升级,更新了一个数据库中间件 - - mycat.查询了一些资料,了解到这是阿里的一个开源项目,基于mysql,是针对磁盘的读与写, ...

  6. UTF-8文件的Unicode签名BOM(Byte Order Mark)问题记录(EF BB BF)

    背景 楼主测试的批量发送信息功能上线之后,后台发现存在少量的ERROR日志,日志内容为手机号码格式不正确. 此前测试过程中没有出现过此类问题,从运营人员拿到的发送列表的TXT,号码是符合规则的,且格式 ...

  7. python UI自动化测试

    为了减小维护成本: 1.UI自动化测试需要有较为稳定的环境 2.代码设计合理,那么我们就需要面向对象的设计一个框架,将重复的代码模块化 一.首先总结一下 UI自动化大概要哪些模块 1.config(配 ...

  8. JS触发服务器控件的单击事件

    <script src="../Js/jquery-1.4.2.min.js" type="text/javascript"></script ...

  9. UVALive-5135 Mining Your Own Business (无向图的双连通分量)

    题目分析:在一张无向图中,将一些点涂上黑色,使得删掉图中任何一个点时,每个连通分量至少有一个黑点.问最少能涂几个黑点,并且在涂最少的情况下有几种方案. 题目分析:显然,一定不能涂割点.对于每一个连通分 ...

  10. C++ 进阶5 拷贝构造 深度复制 运算符重载

    C++ 进阶5 拷贝构造 深度复制 运算符重载 20131026 例子: 运行环境是G++ 编译, /* * main.cpp * *  Created on: 2013年10月26日 *      ...