Проблема XmlDocument.SelectSingleNode и xmlNamespace
Я загружаю строку в документ 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 ответа
Вы должны использовать 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);
Взятые прямо из документации 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);
Таким образом, вам не нужно указывать пространство имен:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml("your xml");
XmlNode node = xmlDoc.SelectSingleNode("/*[local-name() = 'Compile']");
XmlNode nodeToImport = xmlDoc2.ImportNode(node, true);
xmlDoc2.AppendChild(nodeToImport);
Поскольку у "ItemGroup" может быть несколько дочерних элементов "Compile", и вы, в частности, хотите, чтобы "Compile" дочерних элементов "Project/ItemGroup", следующее вернет все желаемые "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:" должна предшествовать каждому уровню узла.