为了账号安全,请及时绑定邮箱和手机立即绑定

通过XmlNamespaceManager使用默认命名空间的Xml-SelectNodes

/ 猿问

通过XmlNamespaceManager使用默认命名空间的Xml-SelectNodes

富国沪深 2020-02-01 16:56:31

我有一些带有默认名称空间的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);

}


查看完整描述

3 回答

?
慕仰0522570

// This will fail with dotnet 3.5sp1. Why? 

//!!!! 

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

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


它是用XPath W3C规范编写的:“使用来自表达式上下文的命名空间声明,将节点测试中的QName扩展为扩展名。这与对开始和结束标记中的元素类型名称进行扩展的方式相同。区别在于不使用用xmlns声明的默认名称空间:如果QName没有前缀,则名称空间URI为null”。


请参见以下网址:w3.org/TR/xpath/#node-tests。


因此,任何没有前缀的名称都被认为是“无名称空间”。在提供的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);

请记住:注册名称空间的全部目的是能够x在任何XPath表达式中使用前缀(在这种情况下为)。


查看完整回答
反对 2020-02-01
?
慕斯王

没有这样的解决方法-XPath W3C规范中写道:“节点测试中的QName使用表达式上下文中的命名空间声明扩展为扩展名称。这与扩展相同。对开始和结束标记中的元素类型名称进行了处理,只是不使用通过xmlns声明的默认名称空间:如果QName没有前缀,则名称空间URI为null”,请参见:w3.org/TR/ xpath /#node-tests。因此,任何没有前缀的名称都被认为是“无名称空间”。b“没有名称空间” 中没有元素,您将获得0个节点

查看完整回答
反对 2020-02-01
?
至尊宝的传说

前面提到的那样,提到上面有关无前缀QName测试的声明仅适用于XPath 1.0可能会有所帮助。在2.0版中,“无前缀的QName ...在表达式上下文中具有默认元素/类型名称空间的名称空间URI”(w3.org/TR/xpath20/#node-tests)在此C#应用程序中无济于事,由于XPath 2.0不可用。但是我想避免有人阅读上面的内容并得出结论,即没有XPath版本允许使用默认名称空间

查看完整回答
反对 2020-02-01

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信