SelectSingleNode returns null when tag contains xmlNamespace
C#XmlXmldocumentSelectsinglenodeSelectnodesC# Problem Overview
I'm loading a string into an XML document that contains the following structure:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Compile Include="clsWorker.cs" />
</ItemGroup>
</Project>
Then I'm loading all into an XmlDocument
:
XmlDocument xmldoc = new XmlDocument();
xmldoc.LoadXml(Xml);
Then the following problem occurs:
XmlNode Node = xmldoc.SelectSingleNode("//Compile"); // returns null
When I remove the xmlns
attribute from the root element (Project
), it works fine.
How do I get SelectSingleNode
to return the relevant element?
C# Solutions
Solution 1 - C#
You should use an XmlNamespaceManager in your call to SelectSingleNode():
XmlNamespaceManager ns = new XmlNamespaceManager(xmldoc.NameTable);
ns.AddNamespace("msbld", "http://schemas.microsoft.com/developer/msbuild/2003");
XmlNode node = xmldoc.SelectSingleNode("//msbld:Compile", ns);
Solution 2 - C#
Taken right from the documentation of SelectSingleNode()
on the MSDN:
>Note
>If the XPath expression does not include a prefix, it is assumed that the
>namespace URI is the empty namespace. If your XML includes a default
>namespace, you must still add a prefix and namespace URI to the
>XmlNamespaceManager; otherwise, you will not get a node selected. For
>more information, see Select Nodes Using XPath Navigation.
And the immediately following sample code is
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("ab", "http://www.lucernepublishing.com");
XmlNode book = doc.SelectSingleNode("//ab:book", nsmgr);
Solution 3 - C#
This way you don't need to specify namespace:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml("your xml");
XmlNode node = xmlDoc.SelectSingleNode("/*[local-name() = 'Compile']");
XmlNode nodeToImport = xmlDoc2.ImportNode(node, true);
xmlDoc2.AppendChild(nodeToImport);
Solution 4 - C#
Since the 'ItemGroup' may have multiple 'Compile' children, and you specifically want the 'Compile' children of 'Project/ItemGroup', the following will return all of the desired 'Compile' children and no others:
XmlDocument projectDoc = new XmlDocument();
projectDoc.Load(projectDocPath);
XmlNamespaceManager ns = new XmlNamespaceManager(projectDoc.NameTable);
ns.AddNamespace("msbld", "http://schemas.microsoft.com/developer/msbuild/2003");
XmlNodeList xnList = projectDoc.SelectNodes(@"/msbld:Project/msbld:ItemGroup/msbld:Compile", ns);
Note that the 'msbld:' namespace specification needs to precede each node level.