【问题标题】:XML namespace alias agnostic .NET XML reader/parsingXML 命名空间别名不可知的 .NET XML 阅读器/解析
【发布时间】:2012-10-05 06:25:10
【问题描述】:

如何读取/解析 XML 命名空间别名未知的 XML 文档? XML 文档的结构和名称空间是已知的,但别名不知道。例如

<?xml version="1.0" encoding="utf-8"?>
<Order xmlns:aa="urn:namespace1"
       xmlns:bb="urn:namespace2">
  <aa:Quantity>1</aa:Quantity>
  <bb:Price>9.98</bb:Price>
</Order>

或者

<?xml version="1.0" encoding="utf-8"?>
<Order xmlns:cc="urn:namespace1"
       xmlns:dd="urn:namespace2">
  <cc:Quantity>1</cc:Quantity>
  <dd:Price>9.98</dd:Price>
</Order>

更新:我事先不知道 XML 命名空间别名。它们可以是任何东西。

我需要使用 AddNameSpace 方法为 XmlNamespaceManager 提供命名空间列表和别名,如下所示:

XPathDocument xDoc = new XPathDocument(“Path to my file”); 
XPathNavigator xNav = xDoc.CreateNavigator();
XmlNamespaceManager xmlns = new XmlNamespaceManager(xNav.NameTable);
xmlns.AddNamespace("aa", "urn:namespace1");
xmlns.AddNamespace("bb", "urn:namespace2");

但这不是 XML 命名空间不可知论者。我的第二个文档使用 cc 和 dd 作为同一个命名空间的别名。

【问题讨论】:

  • 问题是,当然,命名空间存在是有充分理由的,因此您通常在解析 xml 时必须注意它们。然而,有些人通常只是选择去除命名空间——例如,参见stackoverflow.com/questions/987135/…
  • 问题似乎是 AddNamespace() 需要前缀。我假设"urn:namespace1" 在这两种情况下实际上是相同的。使用 XNamespace 可以轻松解决这个问题。你可以使用 XDocument 吗?
  • "urn:namespace1" 在这两种情况下都是同一个实例。是的 - 我可以使用 XDocument,但我的文档可能会变得非常大
  • 这里的一个误解似乎是 C# 代码中使用的命名空间前缀应该与 XML 中使用的命名空间前缀匹配。这没有必要。

标签: c# .net xml xml-parsing xml-namespaces


【解决方案1】:

您提供的代码与名称空间无关的,因为源 XML 中使用的名称空间前缀无关紧要。鉴于您问题中的命名空间定义,您必须使用您在 XPATH 中定义的前缀,例如你必须使用aabb

var quantity = xNav.SelectSingleNode("/Order/aa:Quantity", xmlns);

但是,只要正确使用命名空间urn:namespace1urn:namespace2,此代码仍将成功地从使用前缀ccdd 的XML 中选择。

为了能够在 XPATH 中包含命名空间前缀,您必须使用接受 IXmlNamespaceResolver 的重载。

重申:当您使用以下代码定义命名空间时

xmlns.AddNamespace("aa", "urn:namespace1");

您声明在您的代码中(例如,在您打算使用的 XPATH 中)您将使用命名空间前缀 aa 作为命名空间 urn:namespace1

在要解析的 XML 中,使用属性分配命名空间:

xmlns:cc="urn:namespace1"

字符串urn:namespace1 匹配两个地方以使用该特定命名空间是很重要的。前缀分别是您的代码和 XML 文件的本地前缀,它们不必匹配。

【讨论】:

  • 在您的情况下,XPath 查询需要了解 XML 命名空间别名,例如/Order/aa:Quantity 或 /Order/cc:Quantity 我不认为 XML 命名空间不可知。
  • @Lybecker:您在代码中将别名 aa 分配给了 urn:namespace1。这是您的决定,您可以在代码中使用任何前缀,只要它是唯一的。如果您愿意,您可以使用zz,并且如果您正在处理的XML 使用aacc,即使urn:namespace1 的默认空前缀@ 您的XPATH 仍然会选择您期望的内容。这就是命名空间前缀的美妙之处。它们是真实命名空间的本地别名。
【解决方案2】:

文档中使用的命名空间别名无关紧要 - 它们只是文档中使用的别名,可以是该文档的作者在创作该文档时想要使用的任何名称(它们甚至可以更改中间文档)。

要以与别名无关的方式访问此文档,只需向 XmlNamespaceManager 提供您想要使用的任何别名,然后使用该别名来访问该文档,例如

XmlNamespaceManager xmlns = new XmlNamespaceManager(xNav.NameTable);
xmlns.AddNamespace("foo", "urn:namespace1");
xmlns.AddNamespace("bar", "urn:namespace2");

这些别名不需要与文档中使用的别名匹配 - 这样您就可以使用 XPath 表达式使用这些命名空间的 foobar 别名来导航文档无论文档本身使用的别名如何(只要您提供 XmlNamespaceManager 的实例)。

【讨论】:

    猜你喜欢
    • 2010-11-08
    • 2016-07-08
    • 1970-01-01
    • 1970-01-01
    • 2021-05-03
    • 2014-01-10
    • 1970-01-01
    相关资源
    最近更新 更多