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ą w izolacji w 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 z 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 w przypadku iteracji za pośrednictwem kolekcji zwracanej przez metodę osi XPath LINQ to XML węzły w kolekcji są zwracane w kolejności dokumentu. 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 dokumentów. Poniższa tabela wylicza osie i wskazuje kolejność kolekcji dla każdej z nich:
Oś LINQ to XML | Zamawianie |
---|---|
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.AncestorsAndSelf | 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
, , ancestor
preceding-sibling
i ancestor-or-self
. Na przykład wyrażenie preceding-sibling::*[1]
XPath zwraca bezpośrednio poprzednie elementy równorzędne. Jest to przypadek, mimo że ostateczny zestaw wyników jest przedstawiony w kolejności dokumentu.
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 elementu nadrzędnego elementu, którego dotyczy zapytanie, a nie bezpośredni 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.
Jeśli na przykład masz element w zmiennej o nazwie , i chcesz znaleźć element wnuka o nazwie we wszystkich elementach podrzędnych o nazwie customers
CompanyName
Customer
, należy napisać to 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 to XML |
---|---|
podrzędne (oś domyślna) | XContainer.Elements |
Element nadrzędny (..) | XObject.Parent |
oś atrybutu (@) | XElement.Attribute lub XElement.Attributes |
oś przodka | XNode.Ancestors |
oś ancestor-or-self | XElement.AncestorsAndSelf |
oś potomna (//) | XContainer.Descendants lub XContainer.DescendantNodes |
potomne lub samozwań | XElement.DescendantsAndSelf lub XElement.DescendantNodesAndSelf |
następujące elementy równorzędne | XNode.ElementsAfterSelf lub XNode.NodesAfterSelf |
poprzedni element równorzędny | XNode.ElementsBeforeSelf lub XNode.NodesBeforeSelf |
Następujące | Brak bezpośredniego odpowiednika. |
Poprzednim | Brak bezpośredniego odpowiednika. |