Condividi tramite


Confronto tra XPath e LINQ to XML

XPath e LINQ to XML sono simili in alcuni modi. Entrambi possono essere usati per eseguire query su un albero XML, restituendo risultati come una raccolta di elementi, una raccolta di attributi, una raccolta di nodi o il valore di un elemento o di un attributo. Esistono tuttavia differenze significative tra le due opzioni.

Differenze tra XPath e LINQ to XML

XPath non consente la proiezione di nuovi tipi. Può restituire raccolte di nodi solo dall'albero, mentre LINQ to XML può eseguire una query e proiettare un oggetto grafico o un albero XML in una nuova forma. Le query LINQ to XML possono eseguire molto di più rispetto alle espressioni XPath.

Le espressioni XPath esistono in isolamento all'interno di una stringa. Il compilatore C# non è in grado di analizzare l'espressione XPath in fase di compilazione. Al contrario, le query LINQ to XML vengono analizzate e compilate dal compilatore C#. Il compilatore può rilevare molti errori di query.

I risultati di XPath non sono tipizzati in modo forte. In diverse circostanze, il risultato della valutazione di un'espressione XPath è un oggetto e spetta allo sviluppatore determinare il tipo corretto ed eseguire il cast del risultato in base alle esigenze. Al contrario, le proiezioni di una query LINQ to XML sono fortemente tipizzate.

Ordinamento dei risultati

La raccomandazione XPath 1.0 indica che una raccolta che è il risultato della valutazione di un'espressione XPath non è ordinata.

Tuttavia, quando si esegue l'iterazione di una raccolta restituita da un metodo asse XPath LINQ to XML, i nodi nella raccolta vengono restituiti in ordine di documento. Questo è il caso anche quando si accede agli assi XPath in cui i predicati sono espressi in termini di ordine inverso del documento, ad esempio preceding e preceding-sibling.

Al contrario, la maggior parte degli assi LINQ to XML restituisce raccolte in ordine di documento. Tuttavia, due di esse, Ancestors e AncestorsAndSelf, restituiscono raccolte in ordine di documento inverso. La tabella seguente enumera gli assi e indica l'ordine di raccolta per ognuno di essi:

Asse di LINQ to XML Ordinando
XContainer.DescendantNodes Ordine del documento
XContainer.Descendants Ordine del documento
XContainer.Elements Ordine del documento
XContainer.Nodes Ordine del documento
XContainer.NodesAfterSelf Ordine del documento
XContainer.NodesBeforeSelf Ordine del documento
XElement.AncestorsAndSelf Ordina documento in ordine inverso
XElement.Attributes Ordine del documento
XElement.DescendantNodesAndSelf Ordine del documento
XElement.DiscendentiESeStesso Ordine del documento
XNode.Antenati Ordina documento in ordine inverso
XNode.ElementsAfterSelf Ordine del documento
XNode.ElementsBeforeSelf Ordine del documento
XNode.NodesAfterSelf Ordine del documento
XNode.NodesBeforeSelf Ordine del documento

Predicati posizionale

All'interno di un'espressione XPath, i predicati posizionali sono espressi in termini di ordine di documento per molti assi, ma espressi in ordine di documento inverso per gli assi inversi. Gli assi inversi sono: preceding, preceding-siblingancestor, e ancestor-or-self. Ad esempio, l'espressione XPath preceding-sibling::*[1] restituisce l'elemento di pari livello immediatamente precedente. Questo è il caso anche se il set di risultati finale viene presentato nell'ordine dei documenti.

Al contrario, tutti i predicati posizionali in LINQ to XML sono sempre espressi in termini di ordine dell'asse. Ad esempio, anElement.ElementsBeforeSelf().ElementAt(0) restituisce il primo elemento figlio dell'elemento padre dell'elemento sottoposto a query, non il fratello immediatamente precedente. Un altro esempio: anElement.Ancestors().ElementAt(0) restituisce l'elemento padre.

Se si vuole trovare l'elemento immediatamente precedente in LINQ to XML, è necessario scrivere l'espressione seguente:

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

Differenze di prestazioni

Le query XPath che usano la funzionalità XPath in LINQ to XML saranno più lente rispetto alle query LINQ to XML.

Confronto tra composizione

La composizione di una query LINQ to XML è simile alla composizione di un'espressione XPath, ma la sintassi è molto diversa.

Ad esempio, se si dispone di un elemento in una variabile denominata customers e si vuole trovare un sotto-elemento denominato CompanyName sotto tutti gli elementi figlio denominati Customer, si scriverà questa espressione XPath:

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

La query equivalente LINQ to XML è:

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

Esistono paralleli simili per ognuno degli assi XPath.

Asse XPath Asse di LINQ to XML
child (asse predefinito) XContainer.Elements
Padre (..) XObject.Parent
asse degli attributi (@) XElement.Attribute

o

XElement.Attributes
asse predecessore XNode.Ancestors
asse antenato o se stesso XElement.AncestorsAndSelf
asse discendente (//) XContainer.Descendants

o

XContainer.DescendantNodes
discendente o stesso XElement.DescendantsAndSelf

o

XElement.DescendantNodesAndSelf
seguente fratello XNode.ElementsAfterSelf

o

XNode.NodesAfterSelf
elemento fratello precedente XNode.ElementsBeforeSelf

o

XNode.NodesBeforeSelf
seguente Nessun equivalente diretto.
precedente Nessun equivalente diretto.