Vergelijking van XPath en LINQ naar XML

XPath en LINQ naar XML zijn op een aantal manieren vergelijkbaar. Beide kunnen worden gebruikt om een XML-structuur op te vragen, met resultaten als een verzameling elementen, een verzameling kenmerken, een verzameling knooppunten of de waarde van een element of kenmerk. Er zijn echter aanzienlijke verschillen tussen de twee opties.

Verschillen tussen XPath en LINQ naar XML

XPath staat geen projectie van nieuwe typen toe. Het kan alleen verzamelingen knooppunten van de structuur retourneren, terwijl LINQ naar XML een query kan uitvoeren en een objectgrafiek of een XML-structuur in een nieuwe shape kan projecteren. LINQ naar XML-query's kan veel meer doen dan XPath-expressies.

XPath-expressies bestaan geïsoleerd binnen een tekenreeks. De C#-compiler kan niet helpen bij het parseren van de XPath-expressie tijdens het compileren. LINQ naar XML-query's worden daarentegen geparseerd en gecompileerd door de C#-compiler. De compiler kan veel queryfouten ondervangen.

XPath-resultaten zijn niet sterk getypeerd. In een aantal omstandigheden is het resultaat van het evalueren van een XPath-expressie een object en het is aan de ontwikkelaar om het juiste type te bepalen en het resultaat indien nodig te casten. De projecties van een LINQ naar XML-query worden daarentegen sterk getypeerd.

Resultaatvolgorde

De XPath 1.0-aanbeveling geeft aan dat een verzameling die het resultaat is van het evalueren van een XPath-expressie niet is gerangschikt.

Echter, bij het doorlopen van een verzameling die wordt geretourneerd door een LINQ-naar-XML XPath-as methode, worden de knooppunten in de verzameling in documentvolgorde geretourneerd. Dit is zelfs het geval bij het openen van de XPath-assen waarbij predicaten worden uitgedrukt in omgekeerde documentvolgorde, zoals preceding en preceding-sibling.

De meeste LINQ-naar-XML-assen retourneren daarentegen verzamelingen in documentvolgorde. Twee van hen, Ancestors en AncestorsAndSelf, retourneren echter verzamelingen in omgekeerde documentvolgorde. In de volgende tabel worden de assen opgesomd en wordt de verzamelingsvolgorde voor elke as aangegeven:

LINQ naar XML-axis Bestellen
XContainer.DescendantNodes Documentvolgorde
XContainer.Descendants Documentvolgorde
XContainer.Elements Documentvolgorde
XContainer.Nodes Documentvolgorde
XContainer.NodesAfterSelf Documentvolgorde
XContainer.NodesBeforeSelf Documentvolgorde
XElement.AncestorsAndSelf Omgekeerde documentvolgorde
XElement.Attributes Documentvolgorde
XElement.DescendantNodesAndSelf Documentvolgorde
XElement.DescendantsAndSelf Documentvolgorde
XNode.Ancestors Omgekeerde documentvolgorde
XNode.ElementsAfterSelf Documentvolgorde
XNode.ElementsBeforeSelf Documentvolgorde
XNode.NodesAfterSelf Documentvolgorde
XNode.NodesBeforeSelf Documentvolgorde

Positionele predikaten

In een XPath-expressie worden positionele predicaten uitgedrukt in documentvolgorde voor veel assen, maar worden uitgedrukt in omgekeerde documentvolgorde voor omgekeerde assen. De omgekeerde assen zijn: preceding, preceding-sibling, ancestoren ancestor-or-self. De XPath-expressie preceding-sibling::*[1] retourneert bijvoorbeeld het direct voorafgaande element. Dit is het geval, ook al wordt de uiteindelijke resultatenset weergegeven in documentvolgorde.

Alle positionele predicaten in LINQ naar XML worden daarentegen altijd uitgedrukt in de volgorde van de as. Retourneert bijvoorbeeld anElement.ElementsBeforeSelf().ElementAt(0) het eerste onderliggende element van het bovenliggende element van het opgevraagde element, niet het directe voorafgaande element. Een ander voorbeeld: anElement.Ancestors().ElementAt(0) retourneert het bovenliggende element.

Als u het direct voorafgaande element in LINQ naar XML wilt vinden, schrijft u de volgende expressie:

ElementsBeforeSelf().Last()
ElementsBeforeSelf().Last()

Prestatieverschillen

XPath-query's die gebruikmaken van de XPath-functionaliteit in LINQ naar XML, zijn langzamer dan LINQ naar XML-query's.

Vergelijking van samenstelling

De samenstelling van een LINQ naar XML-query is vergelijkbaar met de samenstelling van een XPath-expressie, maar de syntaxis is heel anders.

Als u bijvoorbeeld een element in een variabele met de naam customershebt en u een kleinkindelement wilt zoeken met de naam CompanyName onder alle onderliggende elementen met de naam Customer, schrijft u deze XPath-expressie:

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

De equivalente LINQ-query voor XML is:

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

Er zijn vergelijkbare parallellen voor elk van de XPath-assen.

XPath-as LINQ naar XML-axis
kind (de standaardas) XContainer.Elements
Ouder (..) XObject.Parent
kenmerkas (@) XElement.Attribute

of

XElement.Attributes
voorouderas XNode.Ancestors
voorouder-of-zelf-as XElement.AncestorsAndSelf
onderliggende as (//) XContainer.Descendants

of

XContainer.DescendantNodes
afstammeling-of-zelf XElement.DescendantsAndSelf

of

XElement.DescendantNodesAndSelf
volgend-broerelement XNode.ElementsAfterSelf

of

XNode.NodesAfterSelf
voorafgaande-broers en zussen XNode.ElementsBeforeSelf

of

XNode.NodesBeforeSelf
volgend Geen direct equivalent.
voorafgaand Geen direct equivalent.