Я пробую очень простой XPath на этот xml (такой же, как показано ниже), и ничего не находит.
Я пробую как .NET, так и этот сайт, а XPath, такие как //PropertyGroup, /PropertyGroup и //MSBuildCommunityTasksPath, просто не работают для меня (они скомпилированы, но возвращают нулевые результаты).
Исходный XML:
<?xml version = "1.0" encoding = "utf-8"?>
<Project xmlns = "http://schemas.microsoft.com/developer/msbuild/2003">
<!-- $Id: FxCop.proj 114 2006-03-14 06:32:46Z pwelter34 $ -->
<PropertyGroup>
<MSBuildCommunityTasksPath>$(MSBuildProjectDirectory)\MSBuild.Community.Tasks\bin\Debug</MSBuildCommunityTasksPath>
</PropertyGroup>
<Import
Project = "$(MSBuildProjectDirectory)\MSBuild.Community.Tasks\MSBuild.Community.Tasks.Targets" />
<Target Name = "DoFxCop">
<FxCop TargetAssemblies = "$(MSBuildCommunityTasksPath)\MSBuild.Community.Tasks.dll"
RuleLibraries = "@(FxCopRuleAssemblies)"
AnalysisReportFileName = "Test.html"
DependencyDirectories = "$(MSBuildCommunityTasksPath)"
FailOnError = "True"
ApplyOutXsl = "True"
OutputXslFileName = "C:\Program Files\Microsoft FxCop 1.32\Xml\FxCopReport.xsl" />
</Target>
</Project>





Ваша проблема связана с пространством имен (xmlns = "http://schemas.microsoft.com/developer/msbuild/2003"). Вы получаете нулевые узлы, потому что вы не квалифицируете его с помощью пространства имен. Если вы удалите атрибут xmlns, ваш XPath "// PropertyGroup" будет работать. Как вы выполняете запрос с пространством имен, обычно включает псевдоним xmlns по умолчанию для идентификатора (поскольку он не указан в атрибуте) и выбор типа «// myXMLNStoken: PropertyGroup».
Теги в документе попадают в пространство имен «по умолчанию», созданное атрибутом xmlns без префикса. К сожалению, только XPath не может запрашивать элементы в пространстве имен по умолчанию. На самом деле я не уверен в семантических деталях, но вы должны явно прикрепить префикс к этому пространству имен, используя любой инструмент, на котором размещен XPath.
В .NET может быть более короткий способ сделать это, но я видел только один способ - через NameSpaceManager. После того, как вы явно добавили пространство имен, вы можете запросить, используя диспетчер пространства имен, как если бы все теги в элементе с пространством имен имели этот префикс (я выбрал msbuild):
using System;
using System.Xml;
public class XPathNamespace {
public static void Main(string[] args) {
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(
@"<?xml version = ""1.0"" encoding = ""utf-8""?>
<Project xmlns = ""http://schemas.microsoft.com/developer/msbuild/2003"">
<!-- $Id: FxCop.proj 114 2006-03-14 06:32:46Z pwelter34 $ -->
<PropertyGroup>
<MSBuildCommunityTasksPath>$(MSBuildProjectDirectory)\MSBuild.Community.Tasks\bin\Debug</MSBuildCommunityTasksPath>
</PropertyGroup>
<Import Project = ""$(MSBuildProjectDirectory)\MSBuild.Community.Tasks\MSBuild.Community.Tasks.Targets""/>
<Target Name = ""DoFxCop"">
<FxCop
TargetAssemblies = ""$(MSBuildCommunityTasksPath)\MSBuild.Community.Tasks.dll""
RuleLibraries = ""@(FxCopRuleAssemblies)""
AnalysisReportFileName = ""Test.html""
DependencyDirectories = ""$(MSBuildCommunityTasksPath)""
FailOnError = ""True""
ApplyOutXsl = ""True""
OutputXslFileName = ""C:\Program Files\Microsoft FxCop 1.32\Xml\FxCopReport.xsl""
/>
</Target>
</Project>");
XmlNamespaceManager namespaceManager = new
XmlNamespaceManager(xmlDocument.NameTable);
namespaceManager.AddNamespace("msbuild", "http://schemas.microsoft.com/developer/msbuild/2003");
foreach (XmlNode n in xmlDocument.SelectNodes("//msbuild:MSBuildCommunityTasksPath", namespaceManager)) {
Console.WriteLine(n.InnerText);
}
}
}
Вы можете добавлять пространства имен в свой код и все такое, но вы можете эффективно использовать подстановочные знаки для пространства имен. Попробуйте следующую идиому XPath.
//*[local-name()='PropertyGroup']
//*[local-name()='MSBuildCommunityTasksPath']
name () обычно также работает, например:
//*[name()='PropertyGroup']
//*[name()='MSBuildCommunityTasksPath']
Обновлено: Пространства имен великолепны, и я не предполагаю, что они не важны, но их использование подстановочных знаков полезно при объединении кода прототипа, одноразовых настольных инструментов, экспериментов с XSLT и т. д. Найдите баланс между потребностями в удобстве и приемлемым риском для поставленной задачи. К вашему сведению, при необходимости вы также можете удалить или переназначить пространства имен.
Спасибо! Вы не представляете, как долго я искал этот ответ. Блестяще!
@Abel Morelos - рад, что помог; когда я, наконец, обнаружил это много месяцев назад, работа с XML так стала намного проще.
Неквалифицированный - плохой поступок. Это эквивалентно запросу столбцов из СУБД без указания таблиц. Как одна строка кода для каждого объявления префикса превращается в «и все такое»?
@grantwparks - я не говорю, что пространства имен бесполезны, но иногда необходимо создать преобразование, которое их игнорирует, а иногда просто удобно не иметь с ними дела. В любом случае это решение пригодится.
ЧАСЫ поиска закончились здесь. СПАСИБО!
Если бы вы могли предоставить короткий образец кода того, что вы пробовали в .net, вам было бы легче предположить, что может пойти не так.