2010-11-13 112 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);