本文介绍了通过XmlNamespaceManager的XML-的SelectNodes使用默认命名空间工作不正常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个默认的命名空间一些XML

 <一的xmlns =瓮:test.Schema'>< B />< B />< / A>
 

和要算的数< B />

我怎么都定义

 的XmlNamespaceManager nsmgr = ????
Assert.AreEqual(2,doc.SelectNodes(// B,nsmgr).Count之间);
 

这样的断言为真?

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

  [测试]
[忽略(为什么这不是工作吗?)
公共无效__DoesNotWork_TestSelectWithDefaultNamespace()
{
    // XML解析与DefaultNamespace的
    XML字符串= @<一的xmlns =瓮:test.Schema'>< B />< B />< / A>中;

    XmlDocument的文档=新的XmlDocument();
    doc.LoadXml(XML);

    //失败,因为XPath不具备空间
    // !!!!
    Assert.AreEqual(2,doc.SelectNodes(// B)计数。);

    //使用XPath DefaultNamespace的
    XmlNamespaceManager的nsmgr =新的XmlNamespaceManager(doc.NameTable);
    nsmgr.AddNamespace(,瓮:test.Schema);

    //这将有DOTNET 3.5SP1失败。为什么?
    // !!!!
    Assert.AreEqual(2,doc.SelectNodes(// B,nsmgr).Count之间);
}

[测试]
公共无效TestSelectWithoutNamespaces_Ok()
{
    // XML来没有命名空间解析
    XML字符串= @< A>< B />< B />< / A>中;

    XmlDocument的文档=新的XmlDocument();
    doc.LoadXml(XML);

    //工程确定
    Assert.AreEqual(2,doc.SelectNodes(// B)计数。);

    //工程确定
    XmlNamespaceManager的nsmgr =新的XmlNamespaceManager(doc.NameTable);
    Assert.AreEqual(2,doc.SelectNodes(// B,nsmgr).Count之间);
}

[测试]
公共无效TestSelectWithNamespaces prefixed_Ok()
{
    // XML解析与DefaultNamespace的
    XML字符串= @<一的xmlns =瓮:test.Schema'>< B />< B />< / A>中;

    XmlDocument的文档=新的XmlDocument();
    doc.LoadXml(XML);

    //使用XPath命名空间通过别名T。工程确定,但XPath是要复杂
    XmlNamespaceManager的nsmgr =新的XmlNamespaceManager(doc.NameTable);
    nsmgr.AddNamespace(T,doc.DocumentElement.NamespaceURI);
    Assert.AreEqual(2,doc.SelectNodes(// T:B,nsmgr).Count之间);
}
 

解决方案

这是一个常见问题解答。在XPath任何未prefixed名称被假定为在没有命名空间。为了选择属于一个命名空间的元素,任何XPath EX pression他们的名字必须是pfixed的是与这个名称空间相关联的preFIX $ P $。该 AddNamespace()方法用于出于这样的目的。它创建了一个特定的命名空间和特定的preFIX之间的绑定。然后,如果这preFIX用于在XPath前pression,由它pfixed元件$ P $可以选择

这是写在 的XPath W3C规范 :的QName中节点测试是使用命名空间中的声明,EX pression背景下展开成一个扩展名,这是同样的方式扩展在开始元素类型名称和结束标记,除了与的xmlns声明的默认命名空间是做不使用:如果QName的不具有preFIX,然后URI为null命名空间。

请参阅此为: w3.org/TR/xpath/#node-tests

所以,任何未prefixed名被认为是在没有命名空间。在所提供的XML文档中有没有命名空间没有​​ B 元素,这就是为什么的XPath EX pression // B 选择任何节点都没有。

使用

 的XmlNamespaceManager nsmanager =新的XmlNamespaceManager();
nsmanager.AddNamespace(×,瓮:test.Schema);
 

后来

  Assert.AreEqual(2 doc.SelectNodes(// X:B。)计数);
 

记住:注册名称空间的全部目的是为了能够使用preFIX(在这种情况下, X )的任何XPath EX pression。

I have some xml with default namespace

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

and want to count the number of <b/>

How do I have to define

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

so that the assert becomes true?

I have tried so far (using 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 is a FAQ. In XPath any unprefixed name is assumed to be in "no namespace". In order to select elements that belong to a namespace, in any XPath expression their names must be prefixed with a prefix that is associated with this namespace. The AddNamespace() method serves exactly this purpose. It creates a binding between a specific namespace and a specific prefix. Then, if this prefix is used in an XPath expression, the element prefixed by it can be selected.

It is written in the XPath W3C spec: "A QName in the node test is expanded into an expanded-name using the namespace declarations from the expression context. This is the same way expansion is done for element type names in start and end-tags except that the default namespace declared with xmlns is not used: if the QName does not have a prefix, then the namespace URI is null".

See this at: w3.org/TR/xpath/#node-tests .

So, any unprefixed name is considered to be in "no namespace". In the provided XML document there are no b elements in "no namespace" and this is why the XPath expression //b selects no nodes at all.

Use:

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

and later:

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

Remember: The whole purpose of registering the namespace is to be able to use the prefix (in this case x) in any XPath expression.

这篇关于通过XmlNamespaceManager的XML-的SelectNodes使用默认命名空间工作不正常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-28 12:47