2010-11-13 113 views
33

我加载一个字符串,其中包含以下结构的XML文档:XmlDocument.SelectSingleNode和XML命名空间的问题

<?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> 

然后即时加载到所有的XmlDocument:

XmlDocument xmldoc = new XmlDocument(); 
xmldoc.LoadXml(Xml); 

那么下面的问题发生:

XmlNode Node = xmldoc.SelectSingleNode("//Compile"); // return null 

当我从根元素(项目)中删除xmlns属性时,其工作正常, 我该如何改进我的SelectSingleNode以返回相关元素?

回答

66

你应该在你的呼叫使用XmlNamespaceManagerSelectSingleNode()

XmlNamespaceManager ns = new XmlNamespaceManager(xmldoc.NameTable); 
ns.AddNamespace("msbld", "http://schemas.microsoft.com/developer/msbuild/2003"); 
XmlNode node = xmldoc.SelectSingleNode("//msbld:Compile", ns); 
+0

这是适用于'SelectNodes'? – 2014-02-27 19:50:54

+0

@ T.S。,是的。 'SelectSingleNode(“xpath”)'大致相当于'SelectNodes(“xpath”)[0]'。 – 2014-02-27 22:22:34

+0

'msbld'从哪里来? – 2015-04-08 05:24:28

16

documentation of SelectSingleNode() on the MSDN右边线:

注意
如果XPath表达式不包含前缀,它假定 命名空间URI是空的命名空间。 如果您的XML包含默认的 名称空间,则仍然必须将前缀和名称空间URI添加到 XmlNamespaceManager;否则,你不会选择一个节点。有关 的更多信息,请参阅Select Nodes Using XPath Navigation

和紧接以下示例代码是

XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable); 
nsmgr.AddNamespace("ab", "http://www.lucernepublishing.com"); 
XmlNode book = doc.SelectSingleNode("//ab:book", nsmgr); 

It'snotasifthiswouldbehiddenknowledge”。 ;-)

+0

最后一句话的链接价值100分! – milesma 2016-11-22 04:55:52

2

由于'ItemGroup'可能有多个'Compile'子元素,并且您特别需要'Project/ItemGroup'的'Compile'子元素,所以下面的代码将返回所有'Compile'子元素其他:

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); 

注意“msbld:”命名空间规范需要先于每个节点的水平。

+0

upvoted为关于多个命名空间规范的警告。 – Bora 2017-02-07 09:15:02

0

这样,您就不需要指定命名空间:

XmlDocument xmlDoc = new XmlDocument(); 
xmlDoc.LoadXml("your xml"); 
XmlNode node = xmlDoc.SelectSingleNode("/*[local-name() = 'Compile']"); 
XmlNode nodeToImport = xmlDoc2.ImportNode(node, true); 
xmlDoc2.AppendChild(nodeToImport);