2010-09-04 12 views
69

Consideremos el siguiente código XML:¿Cómo usar XPath con XElement o LINQ?

<response> 
    <status_code>200</status_code> 
    <status_txt>OK</status_txt> 
    <data> 
    <url>http://bit.ly/b47LVi</url> 
    <hash>b47LVi</hash> 
    <global_hash>9EJa3m</global_hash> 
    <long_url>http://www.tumblr.com/docs/en/api#api_write</long_url> 
    <new_hash>0</new_hash> 
    </data> 
</response> 

Estoy buscando una manera realmente corto para obtener sólo el valor del elemento <hash>. Intenté:

var hash = xml.Element("hash").Value; 

Pero eso no está funcionando. ¿Es posible proporcionar una consulta XPath a un XElement? Puedo hacerlo con la mayor System.Xml marco, haciendo algo como:

xml.Node("/response/data/hash").Value 

¿Hay algo como esto en un espacio de nombres LINQ?


ACTUALIZACIÓN:

Después de monerías con este poco más he encontrado una manera de hacer lo que estoy tratando de hacer:

var hash = xml.Descendants("hash").FirstOrDefault().Value; 

todavía estaría interesado en ver si Alguien tiene una mejor solución?

+3

No utilice FirstOfDefault() en este caso, porque si no se encuentra "hash", obtendrá una NullReferenceException. Use First() en cambio, obtendrá una excepción más descriptiva. – kaalus

+2

Use First() si espera que siempre exista "hash". De lo contrario, FirstOrDefault() está bien siempre que verifique null antes de acceder a la propiedad Value. –

Respuesta

120

Para usar XPath con LINQ a XML, agregue una declaración using para System.Xml.XPath, esto traerá los métodos de extensión de System.Xml.XPath.Extensions al alcance.

En su ejemplo:

var value = (string)xml.XPathEvaluate("/response/data/hash"); 
+1

OK, parece más cercano a la pregunta original –

+3

En realidad, es (¿ahora?) En 'System.Xml.XPath'. –

+0

@DanFriedman no se ha movido. El enlace de nota es para los documentos de clase, un poco antes le doy el espacio de nombres (sin un enlace). – Richard

13

Consulte, cuando se trata de LINQ a XML, ¿por qué no utiliza LINQ para obtener el objeto real.

Los descendientes encuentran cada elemento del XML completo y enumeran todos los objetos que coinciden con el nombre especificado. Entonces, en su caso, hash es el nombre que encuentra.

Así, en lugar de hacer

var hash = xml.Descendants("hash").FirstOrDefault().Value; 

Me resquebrajarse como:

var elements = xml.Descendants("hash"); 
var hash = elements.FirstOrDefault(); 

if(hash != null) 
hash.Value // as hash can be null when default. 

De esta manera también se puede obtener atributos, los nodos elementos etc.

Verificar este artículo para obtener una idea clara al respecto para que ayude. http://www.codeproject.com/KB/linq/LINQtoXML.aspx Espero que esto te ayude.

+2

@adhishek +1 para explicar el valor de separar el elemento de su propia variable para que pueda hacer otras cosas como obtener atributos, etc. –

+1

Una razón para usar XPath es que pierde todas esas cosas que XPath puede hacer y Linq no puede . El primer obvio que viene a la mente es ejecutar una consulta que se define en tiempo de ejecución (digamos una expresión leída de la configuración o lo que sea). –

33

Otros han sugerido completamente razonable cómo utilizar LINQ "nativo" a consultas XML para hacer lo que desee.

Sin embargo, en aras de proporcionar una gran cantidad de alternativas, considere XPathSelectElement, XPathSelectElements y XPathEvaluate para evaluar expresiones XPath en un XNode (son todos los métodos de extensión en XNode). También puede usar CreateNavigator para crear un XPathNavigator para un XNode.

Personalmente, soy un gran fan de usar LINQ to XML API directamente, ya que soy un gran fan de LINQ, pero si te sientes más cómodo con XPath, lo anterior puede ayudarte.

5

Puede utilizar el método .Element() para la cadena de los elementos para formar la estructura similar a XPath.

Para su ejemplo:

XElement xml = XElement.Parse(@"...your xml..."); 
XElement hash = xml.Element("data").Element("hash"); 
+0

Creo esta es la mejor respuesta porque hace el trabajo mientras se continúa utilizando LINQ to XML (lo que se recomienda) en lugar de usar XPath con la consulta LINQ to XML (que no se recomienda). –

+1

Usar XPath es más conciso, especialmente si está buscando un nieto o más. –

1

he tratado de llegar a un marco LINQesq para generar XPath. Se le permite describir XPath usando C# Expresiones Lambda

var xpath = CreateXpath.Where(e => e.TargetElementName == "td" && e.Parent.Name == "tr"); 

var xpath = CreateXpath.Where(e => e.TargetElementName == "td").Select(e => e.Text); 

No estoy seguro si esto es útil en este contexto, pero se puede encontrar documentación aquí:

http://www.syntaxsuccess.com/viewarticle/how-to-create-xpath-using-linq

Cuestiones relacionadas