2011-11-28 22 views
10

Digamos que tengo el siguiente código XML (un ejemplo rápido)Usando XPath para analizar un documento XML

<rows> 
    <row> 
     <name>one</name> 
    </row> 
    <row> 
     <name>two</name> 
    </row> 
</rows> 

Estoy tratando de analizar esto mediante el uso XmlDocument y XPath (en última instancia, por lo que puedo hacer una lista de filas)

Por ejemplo ...

XmlDocument doc = new XmlDocument(); 
doc.LoadXml(xml); 

foreach(XmlNode row in doc.SelectNodes("//row")) 
{ 
    string rowName = row.SelectSingleNode("//name").InnerText; 
} 

Por qué, dentro de mi bucle foreach, es rowName siempre "uno"? Espero que sea "uno" en la primera iteración y "dos" en la segunda.

Parece que // nombre obtiene la primera instancia en el documento, en lugar de la primera instancia en la fila, como era de esperar. Después de todo, estoy llamando al método en el nodo "fila". Si esto es "solo cómo funciona", ¿alguien puede explicar cómo podría cambiarlo para que funcione según mis necesidades?

Gracias

+0

¿qué tal seleccionándolo por // fila/nombre? ¿Esto funciona? – Steve

Respuesta

14

Es el código que envió realmente correcto? Obtengo un error de compilación en row.SelectNode() ya que no es miembro de XmlNode.

De todos modos, mi ejemplo anterior funciona, pero asume un solo <name> nodo dentro del nodo <row> por lo que puede que tenga que utilizar SelectNodes() en lugar de SelectSingleNode() si ese no es el caso.

Como han mostrado otros, use .InnerText para obtener el valor justo.

+0

¡Gracias, y su velocidad le da los 25 completos! Había llegado al extremo de intentar con un solo corte, pero cuando arrojó un error, abandoné y escribí una función para buscar nodos secundarios. Estoy de vuelta en el buen ol XPath ahora :) – musefan

+0

Olvidé el '.InnerText' en mi publicación original, corregido ahora ... y mal escrito' SelectSingleNode' – musefan

3

Utilice una ruta relativa, p. Ej. string rowName = row.SelectSingleNode("name").InnerText;.

2

el problema está en su segunda consulta XPath:

//row 

Esto tiene un alcance global, así que no importa donde usted llama desde, seleccionará todos los row elementos.

que debería funcionar si la sustituye por la expresión siguiente:

.//row 
2

me gustaría utilizar SelectSingleNode, y luego la propiedad InnerText.

var rowName = row.SelectSingleNode("name").InnerText; 
4

Utilice LINQ to XML. Incluir using System.Xml.Linq; en el archivo de código y luego hacer el siguiente código para obtener su lista

XDocument xDoc = XDocument.Load(filepath); 
IEnumerable<XElement> xNames; 

xNames = xDoc.Descendants("name"); 

que le dará una lista de los elementos de nombre. Entonces, si usted quiere convertir eso en un List<string> simplemente hacer esto:

List<string> list = new List<string>(); 
foreach (XElement element in xNames) 
{ 
    list.Add(element.value); 
} 
4

Su segundo XPath comienza con //. Esta es una abreviatura de /descendant-or-self::node(), que puede ver desde /, lo que significa que busca desde la raíz del documento, cualquiera que sea el contexto en el que lo use.

es probable que desee uno de:

var rowName = row.SelectSingleNode("name"); 

para encontrar el name nodos que son hijos inmediatos del row, o

var rowName = row.SelectSingleNode(".//name"); 

encontrar name linfáticos * en cualquier lugar bajo the fila . Note the .` en este segundo xpath que hace que xpath comience desde el nodo de contexto.

0

Usar la siguiente

 doc.LoadXml(xml); 

      foreach(XmlNode row in doc.SelectNodes("/rows/row")) 
      { 
       string rowName = row.SelectSingleNode("//name").InnerText.ToString(); 
      } 
+0

Eso causará el mismo problema que tuve para empezar, lo siento – musefan

+0

Permítanme reformular lol, me deshice de/rows y simplemente lo hice como // row y funcionó para mí. –

Cuestiones relacionadas