【问题标题】:Query for value where a default namespace node exists查询存在默认命名空间节点的值
【发布时间】:2010-05-16 00:07:54
【问题描述】:

我有以下提供给我的 XML,但我无法更改:

<Parent>
  <Settings Version="1234" xmlns="urn:schemas-stuff-com"/>
</Parent>

我正在尝试使用 XPath 检索“版本”属性值。由于 xmlns 的定义没有别名,因此它会自动将该 xmlns 分配给 Settings 节点。当我将此 XML 读入 XMLDocument 并查看 Settings 节点的 namespaceURI 值时,它被设置为“urn:schemas-stuff-com”。

我试过了:

//Parent/Settings/@Version - 返回 Null

//Parent/urn:schemas-stuff-com:Settings/@Version - 无效语法

【问题讨论】:

  • 好问题 (+1)。有关不依赖于特定实现或特定编程语言的解决方案,请参阅我的答案。 :)

标签: .net xml xpath


【解决方案1】:

解决方案取决于您使用的 XPath 版本。在 XPath 2.0 中,以下应该可以工作:

declare namespace foo = "urn:schemas-stuff-com";
xs:string($your_xml//Parent/foo:Settings/@Version)

另一方面,在 XPath 1.0 中,我设法开始工作的唯一解决方案是:

//Parent/*[name() = Settings and namespace-uri() = "urn:schemas-stuff-com"]/@Version

在我看来,XPath 处理器在节点之间更改时不会更改默认命名空间,但我不确定这是否真的如此。

希望这会有所帮助。

【讨论】:

  • namespace() 应该是namespace-uri()
  • 我最终使用了 XPath 1.0 语法,因为其他一些原因我不得不动态创建我不想做的“foo”命名空间名称。不过,您的示例中有一个错字……“设置”应该用单引号引起来。感谢大家的帮助。
【解决方案2】:

使用 XmlNamespaceManager:

XmlDocument doc = new XmlDocument();
doc.Load("file.xml");

XmlNamespaceManager mgr = new XmlNamespaceManager(doc.NameTable);
mgr.AddNamespace("foo", "urn:schemas-stuff-com");

XmlElement settings = doc.SelectSingleNode("Parent/foo:Settings", mgr) as XmlElement;
if (settings != null)
{
  // access settings.GetAttribute("version") here
}

// or alternatively select the attribute itself with XPath e.g.
XmlAttribute version = doc.SelectSingleNode("Parent/foo:Settings/@Version", mgr) as XmlAttribute;
if (version != null)
{
  // access version.Value here
}

【讨论】:

    【解决方案3】:

    除了 Martin Honnen 的正确答案(不幸的是它是特定于实现和编程语言的)之外,这里有一个纯 XPath 解决方案

    /*/*[name()='Settings ']/@Version
    

    【讨论】:

    • 这和我下面的很相似,只是它(可能)也可以捕获其他节点
    猜你喜欢
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多