Проблема XmlDocument.SelectSingleNode и xmlNamespace - PullRequest
40 голосов
/ 13 ноября 2010

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

Ответы [ 4 ]

80 голосов
/ 13 ноября 2010

Вы должны использовать 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);
18 голосов
/ 13 ноября 2010

Взято прямо из документации SelectSingleNode() на MSDN :

Примечание
Если выражение XPath не содержит префикса, предполагается, что URI пространства имен - это пустое пространство имен. Если ваш XML содержит значение по умолчанию пространства имен, вы все равно должны добавить префикс и URI пространства имен к XmlNamespaceManager; в противном случае вы не получите выбранный узел. Для дополнительную информацию см. Выбор узлов с помощью XPath Navigation .

И следующий непосредственно пример кода

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

Это не как , если , то будет быть" скрыто знание ". ; -)

3 голосов
/ 14 июня 2016

Поскольку у 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: должна предшествовать каждому уровню узла.

1 голос
/ 14 февраля 2018

Таким образом, вам не нужно указывать пространство имен:

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