2010-11-13 3 views
33

я загружаю строку в документе XML, который содержит следующую структуру:XmlDocument.SelectSingleNode и XMLNamespace вопрос

<?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 из корневого элемента (Project) его рабочий тон, Как я могу улучшить свой SelectSingleNode, чтобы вернуть соответствующий элемент?

ответ

66

Вы должны использовать XmlNamespaceManager в вызове к SelectSingleNode():

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

+0

@ T.S., Да. 'SelectSingleNode (" xpath ")' примерно эквивалентен 'SelectNodes (" xpath ") [0]'. –

+0

, откуда взялось 'msbld'? –

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'snotasifthiswouldbe "hiddenknowledge". ;-)

+0

Ссылки последнего предложения на 100 баллов! – milesma

2

Поскольку «ItemGroup» может иметь несколько дочерних элементов «Компиляция», и вы специально хотите «Скомпилировать» дочерние элементы «Project/ItemGroup», следующее будет возвращено всем желаемым детям «Компилировать» и нет другие:

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

для предупреждения о множественной спецификации пространства имен. – Bora

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