2008-09-19 36 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); 
     } 
    } 
}