2012-09-26 18 views
11

Estoy tratando de analizar un documento XML. El documento en cuestión es un archivo AppxManifest.¿No puede obtener XmlDocument.SelectNodes para recuperar ninguno de mis nodos?

documento Un ejemplo es el siguiente:

<?xml version="1.0" encoding="utf-8"?> 
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest" xmlns:build="http://schemas.microsoft.com/developer/appx/2012/build" IgnorableNamespaces="build"> 
    <Identity Name="uytury" Publisher="hygj" Version="1.0.0.12" ProcessorArchitecture="neutral" /> 
    <Properties> 
    <DisplayName>jhjj</DisplayName> 
    <PublisherDisplayName>bhhjb</PublisherDisplayName> 
    <Logo>Assets\StoreLogo.png</Logo> 
    </Properties> 
    <Prerequisites> 
    <OSMinVersion>6.2.1</OSMinVersion> 
    <OSMaxVersionTested>6.2.1</OSMaxVersionTested> 
    </Prerequisites> 
    <Resources> 
    <Resource Language="EN" /> 
    </Resources> 
    <Applications> 
    <Application Id="App" Executable="gfg.exe" EntryPoint="gfg.App"> 
     <VisualElements DisplayName="fdsf" Logo="Assets\Logo.png" SmallLogo="Assets\SmallLogo.png" Description="gfdsg" ForegroundText="light" BackgroundColor="#2672EC"> 
     <DefaultTile ShowName="allLogos" WideLogo="Assets\WideLogo.png" ShortName="gfdsg" /> 
     <SplashScreen Image="Assets\SplashScreen.png" BackgroundColor="#2672EC" /> 
     <InitialRotationPreference> 
      <Rotation Preference="portrait" /> 
      <Rotation Preference="landscape" /> 
      <Rotation Preference="portraitFlipped" /> 
      <Rotation Preference="landscapeFlipped" /> 
     </InitialRotationPreference> 
     </VisualElements> 
     <Extensions> 
     <Extension Category="windows.search" /> 
     <Extension Category="windows.shareTarget"> 
      <ShareTarget> 
      <DataFormat>Text</DataFormat> 
      </ShareTarget> 
     </Extension> 
     </Extensions> 
    </Application> 
    </Applications> 
    <build:Metadata> 
    <build:Item Name="TargetFrameworkMoniker" Value=".NETCore,Version=v4.5" /> 
    <build:Item Name="VisualStudio" Version="11.0" /> 
    <build:Item Name="OperatingSystem" Version="6.2.9200.16384 (win8_rtm.120725-1247)" /> 
    <build:Item Name="Microsoft.Build.AppxPackage.dll" Version="11.0.50727.1" /> 
    <build:Item Name="Microsoft.Windows.UI.Xaml.Build.Tasks.dll" Version="11.0.50727.1" /> 
    </build:Metadata> 
</Package> 

trato de analizarlo así:

var xml=new XmlDocument(); 
xml.Load(myfile); 
var mgr=new XmlNamespaceManager(xml.NameTable); 
mgr.AddNamespace("", "http://schemas.microsoft.com/appx/2010/manifest"); 
var nodes=xml.SelectNodes("Applications"); 

Sin embargo, después ejecuto esto, nodes nunca contener cualquier cosa. El documento xml está cargado y así. utilizando SelectNodes("//*") devuelve cada nodo como se esperaba. ¿Cuál es mi problema aquí?

También he intentado muchas variaciones en esa consulta XPath como

  • /Package/Applications/Application
  • Applications/Application
  • Applications/*

No aparece nada para recuperar el nodo sola sin embargo. Idealmente, me gustaría que los nodos contengan todos los nodos Application

+2

Su título habla de XDocument, pero su código usa XmlDocument. Si estuvieras * realmente * usando LINQ to XML, solo recomendaría usar Descendants ... ¿es LINQ to XML una opción? –

+0

@JonSkeet lamentablemente no podemos usar Linq en XML porque apuntamos a .Net 2.0. Sin embargo, quise poner XmlDocument. Siempre me confunden los dos – Earlz

Respuesta

27

Debe usar el espacio de nombres xml específicamente para seleccionarlos. considerar

"//*[local-name()='Applications']/*[local-name()='Application']"  

en su caso, este código también puede funcionar bien:

 var doc = new XmlDocument(); 
     doc.LoadXml(xml); 
     var nsmgr = new XmlNamespaceManager(doc.NameTable); 
     nsmgr.AddNamespace("a", "http://schemas.microsoft.com/appx/2010/manifest"); 
     var nodes = doc.SelectNodes("//a:Applications/a:Application",nsmgr); 
+0

Para el primero me sale "la expresión debe evaluar a un conjunto de nodos" – Earlz

+0

muestra actualizada - faltaba * – aiodintsov

+0

Ah, eso funciona ahora. ¿Por casualidad hay una manera más limpia de hacer esto? Nunca he tratado con espacios de nombres con XPath, así que estoy acostumbrado a algo simple y limpio como '/ Aplicaciones/Aplicación' simplemente trabajando – Earlz

2

puede que tenga que leer este

Aquí está el código:

var xml = new XmlDocument(); 
xml.Load("myXMLFile1.xml"); 
var mgr = new XmlNamespaceManager(xml.NameTable); 
mgr.AddNamespace("", "http://schemas.microsoft.com/appx/2010/manifest"); 
XmlNode root = xml.DocumentElement; 
var nodes = root.SelectNodes("//*[local-name()='Applications']/*[local-name()='Application']"); 
+0

Lo leí :) Simplemente no me di cuenta de que cambiaría mi consulta XPath tan radicalmente en comparación con un archivo XML sin un espacio de nombres – Earlz

7

Debe especificar prefijos para los espacios de nombres en NamespaceManager y XPaths. Tenga en cuenta que los prefijos no necesitan coincidir con nada excepto entre su XPath y su gestor de espacio de nombres *.

var xml=new XmlDocument(); 
xml.Load(myfile); 
var mgr=new XmlNamespaceManager(xml.NameTable); 
mgr.AddNamespace("a", "http://schemas.microsoft.com/appx/2010/manifest"); 
mgr.AddNamespace("bar", "http://schemas.microsoft.com/developer/appx/2012/build"); 
var nodes=xml.SelectNodes("//a:Applications", mgr); 

Y como se señala en otras respuestas XPath que acepta cualquier espacio de nombres es otra opción.

*) I.e. en su muestra particular hay 2 espacios de nombres "predeterminados" (tenga en cuenta que el prefijo predeterminado no es lo mismo que el espacio de nombres vacío) y "compilación". Por lo tanto, cuando defina su administrador de espacios de nombres, debe especificar un prefijo para cada uno de los espacios de nombres (si necesita asignar nodos a ambos), pero los prefijos pueden ser cadenas arbitrarias (válidas para prefijos pero no vacías). Es decir. utilice "a" para el espacio de nombres "predeterminado" y "barra" para el espacio de nombres asignado a "compilar" en el XML.

+0

Heh, eso es extraño. Con ese código, obtengo "Namespace Manager o XsltContext needed. Esta consulta tiene un prefijo, una variable o una función definida por el usuario" que no tiene ningún sentido para mí, ya que tengo un administrador de espacio de nombres. – Earlz

+1

Creo que '' a: Aplicaciones' o 'a: Paquete/a: Aplicaciones', porque ese nodo no está directamente debajo de la raíz. – MiMo

+1

El gestor del espacio de nombres debe pasarse a 'SeleccionarNodos':' SeleccionarNodos ("// a: Aplicaciones", mgr); ' – MiMo

0

No en este caso particular, pero en general, si el espacio de nombres URN en el XML real no es exactamente el mismo usado para agregar un espacio de nombres a un administrador de espacio de nombres (ejemplo: falta una barra final) y un prefijo se especifica en XPath, la consulta puede devolver null.

Si URN espacio de nombres en el XML no es fiable, la sintaxis

"//*[local-name()='tag']" 

va a funcionar.

Cuestiones relacionadas