2008-09-19 60 views
10

我在this xml上嘗試了一個非常基本的XPath(與以下相同),但它沒有找到任何內容。我試圖.NET和this website,XPaths,如//PropertyGroup,/PropertyGroup//MSBuildCommunityTasksPath是根本不爲我工作(他們編譯,但返回零結果)。我的XPath/XML有什麼問題?

源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> 
+0

如果您可以提供您在.net中嘗試過的簡短代碼示例,它可以更容易地建議可能出錯的地方。 – morechilli 2008-09-19 16:49:22

回答

16

你可以在你的代碼和所有添加的命名空間那,但是你可以有效地通配名字空間。嘗試使用以下XPath成語。

//*[local-name()='PropertyGroup'] 
//*[local-name()='MSBuildCommunityTasksPath'] 

名()通常工作以及,如:

//*[name()='PropertyGroup'] 
//*[name()='MSBuildCommunityTasksPath'] 

編輯:命名空間是巨大的,我不建議他們不是重要的,但通配它們派上用場在原型代碼,一次性桌面工具,XSLT實驗等等的基礎上拼湊出來的代碼。平衡您對便利性的需求,以避免可接受的風險。僅供參考,如果需要,您還可以剝離或重新分配名稱空間。

+0

謝謝!你不知道我爲這個答案追了多久。輝煌! – Gerard 2009-07-16 03:53:32

1

你的問題是與命名空間(XMLNS = 「http://schemas.microsoft.com/developer/msbuild/2003」)。您正在接收零節點,因爲您沒有使用命名空間對其進行限定。如果你刪除了xmlns屬性,你的「// PropertyGroup」XPath將會起作用。如何使用命名空間進行查詢通常包括將默認的xmlns別名爲標識符(因爲沒有在屬性中指定),並選擇「// myXMLNStoken:PropertyGroup」。

2

文檔中的標籤最終位於由xmlns屬性創建的「default」名稱空間中,且不帶前綴。不幸的是,單獨的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); 
     } 
    } 
}