2008-09-19 12 views
10

Estoy intentando un XPath muy básico en this xml (lo mismo que a continuación), y no encuentra nada. Estoy intentando .NET y this website, y XPaths como //PropertyGroup, /PropertyGroup y //MSBuildCommunityTasksPath simplemente no funcionan para mí (se compilaron pero devuelven cero resultados).¿Qué pasa con mi XPath/XML?

Fuente 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

Si pudiera proporcionar una muestra de código corto de lo que ha intentado en .net, le resultará más fácil sugerir lo que podría estar fallando. – morechilli

Respuesta

16

Puede añadir espacios de nombres en el código y todo eso, pero puedes efectivamente comodín el espacio de nombres. Pruebe la siguiente frase idiomática de XPath.

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

nombre() por lo general funciona tan bien, como en:

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

EDIT: Los espacios de nombres son grandes y no estoy sugiriendo que no son importantes, pero los comodines les viene muy bien al juntar código de prototipo, herramientas de escritorio únicas, experimentar con XSLT, etc. Equilibre su necesidad de conveniencia contra el riesgo aceptable para la tarea en cuestión. Para su información, si es necesario, también puede quitar o reasignar espacios de nombres.

+0

¡Gracias! No tienes idea de cuánto tiempo he buscado esta respuesta. ¡Brillante! – Gerard

+0

¡Esta respuesta acaba de resolver un problema que estaba teniendo, gracias! –

+0

@Abel Morelos - me alegro de que haya ayudado; cuando finalmente descubrí esto hace muchas lunas hizo que XML funcione ** así que ** es mucho más fácil. –

1

Su problema es con el espacio de nombres (xmlns = "http://schemas.microsoft.com/developer/msbuild/2003"). Está recibiendo cero nodos porque no lo está calificando con el espacio de nombres. Si elimina el atributo xmlns, su XPath "// PropertyGroup" funcionará. La forma de consultar con el espacio de nombres generalmente implica aliasing un xmlns predeterminado a un identificador (ya que uno no se especifica en el atributo) y seleccionando "// myXMLNStoken: PropertyGroup".

2

Las etiquetas en el documento terminan en el espacio de nombres "predeterminado" creado por el atributo xmlns sin prefijo. Desafortunadamente, XPath solo no puede consultar elementos en el espacio de nombres predeterminado. En realidad, no estoy seguro de los detalles semánticos, pero tienes que adjuntar explícitamente un prefijo a ese espacio de nombres usando la herramienta que hospeda XPath.

Puede haber una manera más corta de hacer esto en .NET, pero la única forma que he visto es a través de un NameSpaceManager. Después de agregar explícitamente un espacio de nombres, se puede consultar mediante el gestor de espacio de nombres como si todas las etiquetas en el elemento de espacio de nombres tienen ese prefijo (elegí '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); 
     } 
    } 
}