Udostępnij za pośrednictwem


Porównanie metody XPath i LINQ to XML

XPath i LINQ to XML są podobne w jakiś sposób. Oba te elementy mogą służyć do wykonywania zapytań względem drzewa XML, zwracania takich wyników jak kolekcja elementów, kolekcja atrybutów, kolekcja węzłów lub wartość elementu lub atrybutu. Istnieją jednak znaczące różnice między dwiema opcjami.

Różnice między językami XPath i LINQ to XML

Funkcja XPath nie zezwala na projekcję nowych typów. Może zwracać tylko kolekcje węzłów z drzewa, natomiast LINQ to XML może wykonywać zapytanie i projektować graf obiektu lub drzewo XML w nowym kształcie. Zapytania LINQ to XML mogą wykonywać znacznie więcej niż wyrażenia XPath.

Wyrażenia XPath istnieją jako oddzielne elementy w ramach ciągu. Kompilator języka C# nie może pomóc w analizowaniu wyrażenia XPath w czasie kompilacji. Natomiast zapytania LINQ to XML są analizowane i kompilowane przez kompilator języka C#. Kompilator może przechwytywać wiele błędów zapytań.

Wyniki XPath nie są silnie typizowane. W wielu okolicznościach wynik oceny wyrażenia XPath jest obiektem i zależy od dewelopera w celu określenia odpowiedniego typu i rzutowania wyniku w razie potrzeby. Natomiast projekcje wyników zapytania LINQ to XML są silnie typizowane.

Kolejność wyników

Zalecenie XPath 1.0 wskazuje, że kolekcja, która jest wynikiem oceny wyrażenia XPath, jest nieurządkowana.

Jednak iterując przez kolekcję zwracaną przez metodę osi XPath LINQ to XML, węzły są zwracane w kolejności ich występowania w dokumencie. Jest to przypadek nawet w przypadku uzyskiwania dostępu do osi XPath, w których predykaty są wyrażane pod względem odwrotnej kolejności dokumentów, takich jak preceding i preceding-sibling.

Z kolei większość osi LINQ to XML zwraca kolekcje w kolejności dokumentów. Jednak dwa z nich Ancestors i AncestorsAndSelf zwracają kolekcje w odwrotnej kolejności względem dokumentu. Poniższa tabela wylicza osie i wskazuje kolejność kolekcji dla każdej z nich:

Oś LINQ do XML Zamówienie
XContainer.DescendantNodes Kolejność dokumentów
XContainer.Descendants Kolejność dokumentów
XContainer.Elements Kolejność dokumentów
XContainer.Nodes Kolejność dokumentów
XContainer.NodesAfterSelf Kolejność dokumentów
XContainer.NodesBeforeSelf Kolejność dokumentów
XElement.PrzodkowieIOsobie Odwrotna kolejność dokumentów
XElement.Attributes Kolejność dokumentów
XElement.DescendantNodesAndSelf Kolejność dokumentów
XElement.DescendantsAndSelf Kolejność dokumentów
XNode.Ancestors Odwrotna kolejność dokumentów
XNode.ElementsAfterSelf Kolejność dokumentów
XNode.ElementsBeforeSelf Kolejność dokumentów
XNode.NodesAfterSelf Kolejność dokumentów
XNode.NodesBeforeSelf Kolejność dokumentów

Predykaty pozycyjne

W wyrażeniu XPath predykaty pozycyjne są wyrażane w kolejności dokumentu dla wielu osi, ale są wyrażane w odwrotnej kolejności dokumentu dla osi odwrotnych. Osie odwrotne to: preceding, preceding-sibling, ancestor, i ancestor-or-self. Na przykład wyrażenie XPath preceding-sibling::*[1] zwraca bezpośrednio poprzedni element równorzędny. To nadal prawda, mimo że ostateczny zbiór wyników jest przedstawiony według kolejności dokumentów.

Z kolei wszystkie predykaty pozycyjne w LINQ to XML są zawsze wyrażane pod względem kolejności osi. Na przykład, anElement.ElementsBeforeSelf().ElementAt(0) zwraca pierwszy element podrzędny nadrzędnego elementu sprawdzanego, a nie bezpośredni poprzedzający element równorzędny. Inny przykład: anElement.Ancestors().ElementAt(0) zwraca element nadrzędny.

Jeśli chcesz znaleźć bezpośrednio poprzedni element w linQ to XML, napisz następujące wyrażenie:

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

Różnice wydajności

Zapytania XPath korzystające z funkcji XPath w linQ to XML będą wolniejsze niż zapytania LINQ to XML.

Porównanie kompozycji

Kompozycja zapytania LINQ to XML jest podobna do kompozycji wyrażenia XPath, ale składnia jest bardzo inna.

Na przykład, jeśli masz element w zmiennej o nazwie customers i chcesz znaleźć element wnuka o nazwie CompanyName we wszystkich elementach podrzędnych o nazwie Customer, powinieneś napisać takie wyrażenie XPath:

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

Równoważne zapytanie LINQ to XML:

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

Istnieją podobne równoległości dla każdej osi XPath.

Oś XPath Oś LINQ do XML
dziecko (oś domyślna) XContainer.Elements
Rodzic (..) XObject.Parent
oś atrybutu (@) XElement.Attribute

lub

XElement.Attributes
oś przodka XNode.Ancestors
oś przodka lub siebie XElement.AncestorsAndSelf
oś potomna (//) XContainer.Descendants

lub

XContainer.DescendantNodes
potomek lub ty sam XElement.DescendantsAndSelf

lub

XElement.DescendantNodesAndSelf
następujący element równorzędny XNode.ElementsAfterSelf

lub

XNode.NodesAfterSelf
poprzedni element rodzeństwa XNode.ElementsBeforeSelf

lub

XNode.NodesBeforeSelf
następujący Brak bezpośredniego odpowiednika.
poprzedzający Brak bezpośredniego odpowiednika.