2010-09-04 3 views
69

Betrachten Sie das folgende XML:Wie verwende ich XPath mit XElement oder 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> 

Ich bin für einen wirklich kurzen Weg, um nur den Wert des <hash> Elements zu erhalten. Ich habe versucht:

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

Aber das funktioniert nicht. Ist es möglich, eine XPath-Abfrage an eine XElement bereitzustellen? Ich kann es mit den älteren System.Xml Rahmen tun, wie etwas zu tun:

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

Gibt es so etwas wie dies in einem LINQ-Namespace?


UPDATE:

Nachdem mit diesem monkeying um einige mehr ich einen Weg gefunden zu tun, was ich versuche zu tun: wenn sehen

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

Ich würde noch interessieren Hat jemand eine bessere Lösung?

+3

nicht FirstOfDefault() verwenden, In diesem Fall, wenn "hash" nicht gefunden wird, erhalten Sie eine NullReferenceException. Verwenden Sie stattdessen First(), um eine beschreibende Ausnahme zu erhalten. – kaalus

+2

Verwenden Sie First(), wenn Sie erwarten, dass "hash" immer existiert. Ansonsten ist FirstOrDefault() in Ordnung, solange Sie vor dem Zugriff auf die Value-Eigenschaft auf Null prüfen. –

Antwort

120

Um XPath mit LINQ to XML zu verwenden, fügen Sie eine using-Deklaration für System.Xml.XPath hinzu, dies bringt die Erweiterungsmethoden von System.Xml.XPath.Extensions in den Gültigkeitsbereich.

In Ihrem Beispiel:

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

OK, scheint der ursprünglichen Frage am nächsten zu sein –

+3

Eigentlich ist es (jetzt?) In 'System.Xml.XPath'. –

+0

@DanFriedman es hat sich nicht bewegt. Hinweis Link ist zu Klasse docs, etwas früher gebe ich den Namespace (ohne einen Link). – Richard

13

Sehen Sie, wenn Sie sich mit LINQ zu XML beschäftigen, warum verwenden Sie nicht LINQ, um das tatsächliche Objekt zu erhalten.

Die Nachkommen finden jedes Element aus dem gesamten XML und listet alle Objekte auf, die mit dem angegebenen Namen übereinstimmen. Also in deinem Fall ist Hash der Name, den er findet.

Also, anstatt

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

tun würde ich breche auseinander wie:

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

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

Auf diese Weise können Sie auch Attribute bekommen könnten, sind die Knoten Elemente usw.

Überprüfen dieser Artikel eine klare Vorstellung davon bekommen, damit es hilft. http://www.codeproject.com/KB/linq/LINQtoXML.aspx Ich hoffe, das wird Ihnen helfen.

+2

@adhishek +1 für die Erklärung des Werts der Trennung des Elements zu seiner eigenen Variablen, so dass Sie andere Sachen wie Attribute erhalten können, usw. –

+1

Ein Grund, XPath zu verwenden, ist, dass Sie all diese Dinge verlieren, die XPath tun kann und Linq nicht . Die erste naheliegende Idee besteht darin, eine Abfrage auszuführen, die zur Laufzeit definiert wird (z. B. ein Ausdruck, der aus der Konfiguration gelesen wird oder was auch immer). –

33

Andere haben völlig vernünftig vorgeschlagen, wie Sie "native" LINQ to XML-Abfragen verwenden, um zu tun, was Sie wollen.

jedoch im Interesse der viele Alternativen bietet, betrachten XPathSelectElement, XPathSelectElements und XPathEvaluate XPath-Ausdrücke gegen einen XNode zu bewerten (sie sind alle Erweiterungsmethoden auf XNode). Sie können auch CreateNavigator verwenden, um eine XPathNavigator für eine XNode zu erstellen.

Persönlich bin ich ein großer Fan der Verwendung der LINQ to XML-API direkt, da ich ein großer LINQ-Fan bin, aber wenn Sie sich mit XPath wohler fühlen, kann das obige Ihnen helfen.

5

Sie können .Element() -Methode Kette verwenden Sie die Elemente XPath-ähnliche Struktur zu bilden.

Für Ihr Beispiel:

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

Ich denke Dies ist die beste Antwort, da die Arbeit erledigt wird, während weiterhin LINQ to XML verwendet wird (was empfohlen wird), anstatt XPath mit LINQ to XML-Abfrage zu verwenden (was nicht empfohlen wird). –

+1

Die Verwendung von XPath ist prägnanter, vor allem, wenn Sie nach Großkindern oder darüber hinaus suchen. –

1

Ich habe versucht, mit einem LINQesq Rahmen zu kommen für XPath erzeugen. Damit können Sie mithilfe von XPath C# 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); 

Nicht sicher Ausdrücke beschreiben, wenn dies in diesem Zusammenhang hilfreich ist, aber Sie Dokumentation finden Sie hier: in

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