.NET 使用 XPath 来读写 XML 文件(顺带解决 XML 命名空间的问题)

栏目: 编程语言 · XML · 发布时间: 5年前

内容简介:XPath 是 XML 路径语言(XML Path Language),用来确定XML文档中某部分位置的语言。无论是什么语言什么框架,几乎都可以使用 XPath 来高效查询 XML 文件。本文将介绍 .NET 中的 XPath 相关类型的使用。

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 文件(顺带解决 XML 命名空间的问题)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

机器学习系统设计

机器学习系统设计

[德] Willi Richert、Luis Pedro Coelho / 刘峰 / 人民邮电出版社 / 2014-7-1 / CNY 49.00

如今,机器学习正在互联网上下掀起热潮,而Python则是非常适合开发机器学习系统的一门优秀语言。作为动态语言,它支持快速探索和实验,并且针对Python的机器学习算法库的数量也与日俱增。本书最大的特色,就是结合实例分析教会读者如何通过机器学习解决实际问题。 本书将向读者展示如何从原始数据中发现模式,首先从Python与机器学习的关系讲起,再介绍一些库,然后就开始基于数据集进行比较正式的项目开......一起来看看 《机器学习系统设计》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

URL 编码/解码
URL 编码/解码

URL 编码/解码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器