2009-07-08 21 views
11

Pregunta simple, solo quiero seleccionar el texto de la etiqueta <Plantilla>. Esto es lo que tengo, pero el Xpath no coincide con nada.¿Cómo seleccionar nodos con XPath en C#?

public static void TestXPath() 
{ 
    string xmlText = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"; 
    xmlText += "<Properties xmlns=\"http://schemas.openxmlformats.org/officeDocument/2006/extended-properties\" xmlns:vt=\"http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes\">"; 
    xmlText += "<Template>Normal</Template> <TotalTime>1</TotalTime> <Pages>1</Pages> <Words>6</Words>"; 
    xmlText += "</Properties>"; 

    XmlDocument xmlDoc = new XmlDocument(); 
    xmlDoc.Load(new System.IO.StringReader(xmlText)); 

    foreach (XmlNode node in xmlDoc.SelectNodes("//Template")) 
    { 
     Console.WriteLine("{0}: {1}", node.Name, node.InnerText); 
    } 
} 

Respuesta

24

Es necesario utilizar un XmlNamespaceManager porque el elemento de plantilla se encuentra en un espacio de nombres:

XmlDocument xmlDoc = new XmlDocument(); 
xmlDoc.Load(new System.IO.StringReader(xmlText)); 
XmlNamespaceManager manager = new XmlNamespaceManager(xmlDoc.NameTable); 
manager.AddNamespace("ns", 
    "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties"); 

foreach (XmlNode node in xmlDoc.SelectNodes("//ns:Template", manager)) 
{ 
    Console.WriteLine("{0}: {1}", node.Name, node.InnerText); 
} 
7

Eso es una cuestión de espacio de nombres; necesita obtener la tabla de nombres, elegir un alias y usar eso en su consulta. O tal vez (en este caso) intente GetElementsByTagName.

XmlNamespaceManager mgr = new XmlNamespaceManager(xmlDoc.NameTable); 
mgr.AddNamespace("x", 
    "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties"); 
foreach (XmlNode node in xmlDoc.SelectNodes("//x:Template", mgr)) 
{ 
    Console.WriteLine("{0}: {1}", node.Name, node.InnerText); 
} 

O:

foreach (XmlNode node in xmlDoc.GetElementsByTagName("Template")) 
{ 
    Console.WriteLine("{0}: {1}", node.Name, node.InnerText); 
} 
+0

¡No tenía idea de que tuviera que elegir un alias arbitrario para resolver apropiadamente las consultas XPath de esta manera! Gracias por la información Marc. –

4

Aquí su expresión XPath requiere una resolución de espacio de nombres. tiene que instanciar un XmlNamespaceManager y usarlo en sus SelectNodes.

esta muestra debe trabajar

public static void TestXPath() 
    { 
     string xmlText = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"; 
     xmlText += "<Properties xmlns=\"http://schemas.openxmlformats.org/officeDocument/2006/extended-properties\" xmlns:vt=\"http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes\">"; 
     xmlText += "<Template>Normal</Template> <TotalTime>1</TotalTime> <Pages>1</Pages> <Words>6</Words>"; 
     xmlText += "</Properties>"; 

     XmlDocument xmlDoc = new XmlDocument(); 
     xmlDoc.Load(new System.IO.StringReader(xmlText)); 

     XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable); 
     nsmgr.AddNamespace("res", "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties"); 

     foreach (XmlNode node in xmlDoc.SelectNodes("//res:Template", nsmgr)) 
     { 
      Console.WriteLine("{0}: {1}", node.Name, node.InnerText); 
     } 
    } 

también se puede obtener el espacio de nombres predeterminado utilizando y escribir

string s = xmlDoc.DocumentElement.GetNamespaceOfPrefix(""); 
nsmgr.AddNamespace("ns", s); 
2

¿Por qué necesita el espacio de nombres aquí de todos modos? acaba de deshacerse de estos

xmlns=\"http://schemas.openxmlformats.org/officeDocument/2006/extended-properties\" 
xmlns:vt=\"http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes\" 

y su selección va a funcionar.

Cuestiones relacionadas