Что не так с моим XPath / XML?
-
01-07-2019 - |
Вопрос
Я пробую очень простой XPath на этот xml- файл (то же, что и ниже), и он ничего не находит.Я пробую и то, и другое.СЕТЬ и этот веб-сайт, и XPaths , такие как //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>
Решение
Вы можете добавлять пространства имен в свой код и все такое, но вы можете эффективно использовать подстановочные знаки для пространства имен.Попробуйте использовать следующую идиому XPath.
//*[local-name()='PropertyGroup']
//*[local-name()='MSBuildCommunityTasksPath']
name() обычно работает так же хорошо, как и в:
//*[name()='PropertyGroup']
//*[name()='MSBuildCommunityTasksPath']
Редактировать: Пространства имен - это здорово и я не утверждаю, что они не важны, но их подстановочные знаки пригодятся при создании прототипа кода, одноразовых инструментов для настольных компьютеров, экспериментировании с XSLT и так далее.Сбалансируйте свою потребность в удобстве с приемлемым риском для выполнения поставленной задачи.К вашему сведению, при необходимости вы также можете удалить или переназначить пространства имен.
Другие советы
Теги в документе попадают в пространство имен "по умолчанию", созданное атрибутом 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);
}
}
}
Ваша проблема связана с пространством имен (xmlns="http://schemas.microsoft.com/developer/msbuild/2003").Вы получаете нулевые узлы, потому что вы не указываете их в пространстве имен.Если вы удалите атрибут xmlns, ваш XPath "//PropertyGroup" будет работать.То, как вы выполняете запрос с помощью пространства имен, обычно включает в себя присвоение идентификатора xmlns по умолчанию идентификатору (поскольку он не указан в атрибуте) и выбор типа "//myXMLNStoken:PropertyGroup".