<?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" >
var xmlns = new XmlNamespaceManager(new NameTable());
xmlns.AddNamespace(string.Empty, "http://demo.com/2011/demo-schema");
var xelements = xdoc.XPathSelectElements("/Report/ReportInfo/Name", xmlns);
Assert.AreEqual(0, xelements.Count());
[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.