XPath/XML の何が問題なのでしょうか?
-
01-07-2019 - |
質問
非常に基本的な 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>
解決
コードなどに名前空間を追加できますが、名前空間を効果的にワイルドカード化することもできます。次の 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 属性を削除すると、「//PropertyGroup」XPath が機能します。名前空間を使用してクエリを実行するには、通常、デフォルトの xmlns を識別子にエイリアス化し (属性に識別子が指定されていないため)、「//myXMLNStoken:PropertyGroup」のように選択する必要があります。