Freigeben über


Vergleich von XPath mit LINQ to XML

XPath und LINQ to XML haben hinsichtlich ihrer Funktionalität einige Gemeinsamkeiten. Beide können verwendet werden, um Elementauflistungen, Attributauflistungen, Knotenauflistungen oder die Werte von Elementen oder Attributen aus XML-Strukturen abzurufen. Aber es gibt auch einige Unterschiede.

Unterschiede zwischen XPath und LINQ to XML

XPath lässt keine Projektion neuer Typen zu Es können nur Auflistungen der Knoten aus der Struktur zurückgegeben werden. LINQ to XML kann dagegen eine Abfrage ausführen und ein Objektdiagramm oder eine XML-Struktur in einer neuen Form projizieren. LINQ to XML-Abfragen umfassen deutlich mehr Funktionen und sind viel leistungsstärker als XPath-Ausdrücke.

XPath-Ausdrücke existieren innerhalb einer Zeichenfolge isoliert. Der C#- oder Visual Basic-Compiler kann nicht helfen, den XPath-Ausdruck beim Kompilieren zu analysieren. LINQ to XML-Abfragen werden dagegen vom C#- oder Visual Basic-Compiler analysiert und kompiliert. Der Compiler kann eine Vielzahl von Abfragefehlern abfangen.

XPath-Ergebnisse sind nicht stark typisiert. In vielen Situationen ist das Ergebnis der Auswertung eines XPath-Ausdrucks ein Objekt, und es obliegt dem Entwickler, den richtigen Typ zu bestimmen und das Ergebnis nach Bedarf zu konvertieren. Im Gegensatz dazu sind die Projektionen aus einer LINQ to XML-Abfrage stark typisiert.

Reihenfolge der Ergebnisanzeige

Laut XPath 1.0-Empfehlung ist eine Auflistung, die das Ergebnis der Auswertung eines XPath-Ausdrucks ist, nicht geordnet.

Beim Durchlaufen einer Auflistung, die von einer LINQ to XML-XPath-Achsenmethode zurückgegeben wurde, werden die Knoten in der Auflistung jedoch in der Dokumentreihenfolge zurückgegeben. Dies ist auch beim Zugriff auf die XPath-Achsen der Fall, wo beim Ausdrücken von Prädikaten auf die umgekehrte Dokumentreihenfolge zurückgegriffen wird, wie z. B. preceding und preceding-sibling.

Die meisten LINQ to XML-Achsen geben Auflistungen in der Dokumentreihenfolge zurück, aber bei zweien, Ancestors und AncestorsAndSelf, werden die Auflistungen in umgekehrter Dokumentreihenfolge zurückgegeben. In der folgenden Tabelle werden die Achsen aufgeführt, und es wird jeweils die Auflistungsreihenfolge angegeben:

LINQ to XML-Achse

Sortieren

XContainer.DescendantNodes

Dokumentreihenfolge

XContainer.Descendants

Dokumentreihenfolge

XContainer.Elements

Dokumentreihenfolge

XContainer.Nodes

Dokumentreihenfolge

XContainer.NodesAfterSelf

Dokumentreihenfolge

XContainer.NodesBeforeSelf

Dokumentreihenfolge

XElement.AncestorsAndSelf

Umgekehrte Dokumentreihenfolge

XElement.Attributes

Dokumentreihenfolge

XElement.DescendantNodesAndSelf

Dokumentreihenfolge

XElement.DescendantsAndSelf

Dokumentreihenfolge

XNode.Ancestors

Umgekehrte Dokumentreihenfolge

XNode.ElementsAfterSelf

Dokumentreihenfolge

XNode.ElementsBeforeSelf

Dokumentreihenfolge

XNode.NodesAfterSelf

Dokumentreihenfolge

XNode.NodesBeforeSelf

Dokumentreihenfolge

Positionsprädikate

Innerhalb von XPath-Ausdrücken werden Positionsprädikate bei vielen Achsen in der Dokumentreihenfolge angegeben, aber bei den rückwärts gerichteten Achsen preceding, preceding-sibling, ancestor und ancestor-or-self wird die umgekehrte Dokumentreihenfolge verwendet. So gibt z. B. der XPath-Ausdruck preceding-sibling::*[1] das unmittelbar vorausgehende nebengeordnete Element zurück, auch wenn das endgültige Resultset in der Dokumentreihenfolge angegeben wird.

Dagegen werden alle Positionsprädikate in LINQ to XML stets in der Reihenfolge der Achse angegeben. So wird z. B. bei anElement.ElementsBeforeSelf().ToList()[0] statt des unmittelbar vorausgehenden nebengeordneten Elements das erste untergeordnete Element der Ebene oberhalb des abgefragten Elements zurückgegeben. Ein anderes Beispiel: anElement.Ancestors().ToList()[0] gibt das übergeordnete Element zurück.

Beachten Sie, dass bei der oben beschriebenen Herangehensweise die gesamte Auflistung materialisiert wird. Dies ist nicht die effizienteste Art, diese Abfrage zu schreiben. Die Abfrage in der dargestellten Form soll lediglich das Verhalten der Positionsprädikate zeigen. Dieselbe Abfrage könnte vernünftiger mit der First-Methode geschrieben werden: anElement.ElementsBeforeSelf().First().

Wenn Sie für die Suche nach dem unmittelbar vorausgehenden Element LINQ to XML verwenden möchten, müssten Sie den folgenden Ausdruck schreiben:

ElementsBeforeSelf().Last()

Leistungsunterschiede

XPath-Abfragen, die die XPath-Funktionalität in LINQ to XML verwenden, sind nicht so schnell, wie LINQ to XML-Abfragen.

Verfassen von Abfragen im Vergleich

Das Verfassen einer LINQ to XML-Abfrage weist Parallelen mit dem Verfassen eines XPath-Ausdrucks auf, beide haben aber eine sehr unterschiedliche Syntax.

Wenn Sie z. B. ein Element in einer Variable namens customers haben und in allen untergeordneten Elementen mit dem Namen Customer nach einem Element der zweiten Unterebene namens CompanyName suchen, würden Sie den folgenden XPath-Ausdruck schreiben:

customers.XPathSelectElements("./Customer/CompanyName");
customers.XPathSelectElements("./Customer/CompanyName")

Die entsprechende LINQ to XML-Abfrage würde wie folgt lauten:

customers.Element("Customer").Elements("CompanyName");
customers.Element("Customer").Elements("CompanyName")

Ähnliche Parallelen gibt es auch bei allen anderen XPath-Achsen.

XPath-Achse

LINQ to XML-Achse

child (Standardachse)

XContainer.Elements

parent (..)

XObject.Parent

@ (Attributachse)

XElement.Attribute

oder

XElement.Attributes

ancestor-Achse

XNode.Ancestors

ancestor-or-self-Achse

XElement.AncestorsAndSelf

descendant (//)

XContainer.Descendants

oder

XContainer.DescendantNodes

descendant-or-self

XElement.DescendantsAndSelf

oder

XElement.DescendantNodesAndSelf

following-sibling

XNode.ElementsAfterSelf

oder

XNode.NodesAfterSelf

preceding-sibling

XNode.ElementsBeforeSelf

oder

XNode.NodesBeforeSelf

following

Keine direkte Entsprechung.

preceding

Keine direkte Entsprechung.

Siehe auch

Konzepte

LINQ to XML für XPath-Benutzer