gpt4 book ai didi

c# - 通过 XmlNamespaceManager 具有默认命名空间的 Xml-SelectNodes 无法按预期工作

转载 作者:可可西里 更新时间:2023-11-01 08:03:03 31 4
gpt4 key购买 nike

我有一些带有默认命名空间的 xml

<a xmlns='urn:test.Schema'><b/><b/></a>

并想统计 <b/> 的数量

我该如何定义

XmlNamespaceManager nsmgr = ????
Assert.AreEqual(2, doc.SelectNodes("//b", nsmgr).Count);

以便断言变为真?

到目前为止我已经尝试过(使用 nunit):

[Test]
[Ignore("Why does this not work?")]
public void __DoesNotWork_TestSelectWithDefaultNamespace()
{
// xml to parse with defaultnamespace
string xml = @"<a xmlns='urn:test.Schema'><b/><b/></a>";

XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);

// fails because xpath does not have the namespace
//!!!!
Assert.AreEqual(2, doc.SelectNodes("//b").Count);

// using XPath defaultnamespace
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("", "urn:test.Schema");

// This will fail with dotnet 3.5sp1. Why?
//!!!!
Assert.AreEqual(2, doc.SelectNodes("//b", nsmgr).Count);
}

[Test]
public void TestSelectWithoutNamespaces_Ok()
{
// xml to parse without namespace
string xml = @"<a><b/><b/></a>";

XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);

// works ok
Assert.AreEqual(2, doc.SelectNodes("//b").Count);

// works ok
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
Assert.AreEqual(2, doc.SelectNodes("//b", nsmgr).Count);
}

[Test]
public void TestSelectWithNamespacesPrefixed_Ok()
{
// xml to parse with defaultnamespace
string xml = @"<a xmlns='urn:test.Schema'><b/><b/></a>";

XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);

// using XPath namespace via alias "t". works ok but xpath is to complicated
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("t", doc.DocumentElement.NamespaceURI);
Assert.AreEqual(2, doc.SelectNodes("//t:b", nsmgr).Count);
}

最佳答案

// This will fail with dotnet 3.5sp1. Why? 
//!!!!
Assert.AreEqual(2, doc.SelectNodes("//b", nsmgr).Count);

这是一个常见问题解答。在 XPath 中,任何没有前缀的名称都被假定为在“无 namespace ”中。为了选择属于命名空间的元素,在任何 XPath 表达式中,它们的名称必须以与该命名空间关联的前缀为前缀。 AddNamespace() 方法正是用于此目的。它在特定 namespace 和特定前缀之间创建绑定(bind)。然后,如果在 XPath 表达式中使用此前缀,则可以选择以它为前缀的元素。

它写在 XPath W3C spec :“节点测试中的 QName 使用表达式上下文中的命名空间声明扩展为扩展名称。这与开始和结束标记中的元素类型名称的扩展方式相同,除了默认值不使用用 xmlns 声明的 namespace :如果 QName 没有前缀,则 namespace URI 为空”。

参见: w3.org/TR/xpath/#node-tests

因此,任何没有前缀的名称都被视为“无 namespace ”。在提供的 XML 文档中,“无命名空间”中没有 b 元素,这就是 XPath 表达式 //b 根本不选择任何节点的原因。

使用:

XmlNamespaceManager nsmanager = new XmlNamespaceManager(doc.NameTable);
nsmanager.AddNamespace("x", "urn:test.Schema");

及更高版本:

Assert.AreEqual(2, doc.SelectNodes("//x:b", nsmanager).Count);

记住:注册命名空间的全部目的是能够在任何 XPath 表达式中使用前缀(在本例中为 x)。

关于c# - 通过 XmlNamespaceManager 具有默认命名空间的 Xml-SelectNodes 无法按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4271689/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com