Default namespace not working in Dotnet API.

As in one of my post in some other site, I discuss the possibility of working with Xml Linq with XPath. However, let see if we have a XML file that has thefollowing contents.

<?xml version="1.0" encoding="utf-8"?>
<Report Id="ID1" Type="Demo Report" Created="2011-01-01T01:01:01+11:00" Culture="en" xmlns="http://demo.com/2011/demo-schema">
    <ReportInfo>
        <Name>Demo Report</Name>
        <CreatedBy>Unit Test</CreatedBy>
    </ReportInfo>
</Report>


as you can see the it has default xmlns set to something other than empty.

<Report ... xmlns="http://demo.com/2011/demo-schema" > 

So, if you think that you can create a XmlNamespaceManager, and add the string.Empty as the key and the URI in the default namespace as the above xml. And then you construct the Xpath and query the Xpath result. 


var xmlns = new XmlNamespaceManager(new NameTable());
      xmlns.AddNamespace(string.Empty, "http://demo.com/2011/demo-schema");
      var xelements = xdoc.XPathSelectElements("/Report/ReportInfo/Name", xmlns);

You may get a empty result. (it is not null as you might expect the result to be when no element that match that criteria).

 Assert.AreEqual(0, xelements.Count());

Here is the source that verify that. 


[Test]
    public void TestStackOverflow_Example()
    {
      var xmlstring = @"<?xml version=""1.0"" encoding=""utf-8""?>
<Report Id=""ID1"" Type=""Demo Report"" Created=""2011-01-01T01:01:01+11:00"" Culture=""en"" xmlns=""http://demo.com/2011/demo-schema"">
    <ReportInfo>
        <Name>Demo Report</Name>
        <CreatedBy>Unit Test</CreatedBy>
    </ReportInfo>
</Report>";

      // the XML without namespace is working fine with the Xpath string. however, what is missing in the Xpath one?
//      var xmlstring = @"<?xml version=""1.0"" encoding=""utf-8""?>
//<Report Id=""ID1"" Type=""Demo Report"" Created=""2011-01-01T01:01:01+11:00"" Culture=""en"" >
//    <ReportInfo>
//        <Name>Demo Report</Name>
//        <CreatedBy>Unit Test</CreatedBy>
//    </ReportInfo>
//</Report>";


      var buffer = System.Text.ASCIIEncoding.ASCII.GetBytes(xmlstring);
      var memory = new MemoryStream(buffer);
      memory.Seek(0, SeekOrigin.Begin);

      var xdoc = XDocument.Load(memory);
      Console.WriteLine("xdoc = \n" + xdoc.ToString());
      var xmlns = new XmlNamespaceManager(new NameTable());
      xmlns.AddNamespace(string.Empty, "http://demo.com/2011/demo-schema");
      Assert.AreEqual("http://demo.com/2011/demo-schema", xmlns.DefaultNamespace);

      var xelements = xdoc.XPathSelectElements("/Report/ReportInfo/Name", xmlns);
      Assert.IsNotNull(xelements);
      Assert.AreEqual(0, xelements.Count());

      // This shows the correct way to do the Xpath query when Default XNamespace is not supported because of 
      // XPath 1.0 does not support default namespace
      xmlns.AddNamespace("empty", "http://demo.com/2011/demo-schema");
      var xelements2 = xdoc.XPathSelectElements("/empty:Report/empty:ReportInfo/empty:Name", xmlns);
      Assert.IsNotNull(xelements2);
      Assert.AreEqual(1, xelements2.Count());

    }



So what is the reason? From the post in stack overflow.  in quoted.

<quoted>

When using XPath in .NET (via a navigator or SelectNodes/SelectSingleNode) on XML with namespaces you need to:

  • provide your own XmlNamespaceManager

  • and explicitly prefix all elements in XPath expression, which are in namespace.

The latter is (paraphrased from MS source linked below): because XPath 1.0 ignores default namespace (xmlns="some_namespace") specifications. So when you use element name without prefix it assumes null namespace.

That's why .NET implementation of XPath ignores namespace with prefix String.Empty in XmlNamespaceManager and allways uses null namespace.

See XmlNamespaceManager and UndefinedXsltContext don't handle default namespace for more information.

I find this "feature" very inconvenient because you cannot make old XPath namespace-aware by simply adding default namespace declaration, but that's how it works.

</quoted>


So , so the remedy for this non-empty default namespace, you have to qualify the names with certain prefix strings. As you might already find out in the Test code above.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值