Porovnání jazyka XPath a technologie LINQ to XML
XPath a LINQ to XML jsou podobné některým způsobem. Obojí lze použít k dotazování stromu XML, který vrací například výsledky jako kolekci prvků, kolekci atributů, kolekci uzlů nebo hodnotu elementu nebo atributu. Mezi těmito dvěma možnostmi však existují významné rozdíly.
Rozdíly mezi XPath a LINQ to XML
XPath neumožňuje projekci nových typů. Může vracet pouze kolekce uzlů ze stromu, zatímco LINQ to XML může spustit dotaz a projektovat objektový graf nebo strom XML v novém obrazci. Dotazy LINQ to XML mohou provádět mnohem více než výrazy XPath.
Výrazy XPath existují izolovaně v řetězci. Kompilátor jazyka C# nemůže pomoct analyzovat výraz XPath v době kompilace. Naproti tomu dotazy LINQ to XML se parsují a kompilují kompilátorem jazyka C#. Kompilátor může zachytit mnoho chyb dotazu.
Výsledky XPath nejsou silného typu. V řadě okolností je výsledkem vyhodnocení výrazu XPath objekt a je na vývojáři, aby určil správný typ a v případě potřeby výsledek přetypuje. Naproti tomu projekce z dotazu LINQ to XML jsou silně napsané.
Řazení výsledků
Doporučení XPath 1.0 uvádí, že kolekce, která je výsledkem vyhodnocení výrazu XPath, není seřazená.
Při iteraci kolekcí vrácenou metodou osy XPath LINQ to XML se však uzly v kolekci vrátí v pořadí dokumentu. To je případ i při přístupu k osám XPath, kde jsou predikáty vyjádřeny z hlediska pořadí obráceného dokumentu, například preceding
a preceding-sibling
.
Naproti tomu většina os LINQ to XML vrací kolekce v pořadí dokumentů. Dva z nich Ancestors ale vrátí AncestorsAndSelfkolekce v obráceném pořadí dokumentů. Následující tabulka uvádí osy a označuje pořadí kolekcí pro každou z nich:
Osa LINQ to XML | Řazení |
---|---|
XContainer.DescendantNodes | Pořadí dokumentů |
XContainer.Descendants | Pořadí dokumentů |
XContainer.Elements | Pořadí dokumentů |
XContainer.Nodes | Pořadí dokumentů |
XContainer.NodesAfterSelf | Pořadí dokumentů |
XContainer.NodesBeforeSelf | Pořadí dokumentů |
XElement.AncestorsAndSelf | Obrácené pořadí dokumentů |
XElement.Attributes | Pořadí dokumentů |
XElement.DescendantNodesAndSelf | Pořadí dokumentů |
XElement.DescendantsAndSelf | Pořadí dokumentů |
XNode.Předky | Obrácené pořadí dokumentů |
XNode.ElementsAfterSelf | Pořadí dokumentů |
XNode.ElementsBeforeSelf | Pořadí dokumentů |
XNode.NodesAfterSelf | Pořadí dokumentů |
XNode.NodesBeforeSelf | Pořadí dokumentů |
Poziční predikáty
Ve výrazu XPath jsou poziční predikáty vyjádřeny z hlediska pořadí dokumentů pro mnoho os, ale jsou vyjádřeny v obráceném pořadí dokumentu pro obrácené osy. Obrácené osy jsou: preceding
, preceding-sibling
, ancestor
a ancestor-or-self
. Například výraz preceding-sibling::*[1]
XPath vrátí bezprostředně předcházející stejné stejné hodnoty. To je případ, i když se konečná sada výsledků zobrazí v pořadí dokumentu.
Naproti tomu všechny poziční predikáty v JAZYCE LINQ to XML jsou vždy vyjádřeny z hlediska pořadí osy. Například anElement.ElementsBeforeSelf().ElementAt(0)
vrátí první podřízený prvek nadřazeného prvku dotazovaného prvku, nikoli bezprostředně předcházející stejné úrovně. Další příklad: anElement.Ancestors().ElementAt(0)
vrátí nadřazený prvek.
Pokud byste chtěli najít bezprostředně předcházející prvek v JAZYCE LINQ to XML, napsali byste následující výraz:
ElementsBeforeSelf().Last()
ElementsBeforeSelf().Last()
Rozdíly v výkonu
Dotazy XPath, které používají funkce XPath v LINQ to XML, budou pomalejší než dotazy LINQ to XML.
Porovnání složení
Složení dotazu LINQ to XML je podobné složení výrazu XPath, ale syntaxe je velmi odlišná.
Pokud například máte prvek v proměnné s názvem customers
a chcete najít vnoučácký prvek pojmenovaný CompanyName
pod všemi podřízenými elementy s názvem Customer
, napíšete tento výraz XPath:
customers.XPathSelectElements("./Customer/CompanyName")
customers.XPathSelectElements("./Customer/CompanyName")
Ekvivalentní dotaz LINQ to XML je:
customers.Elements("Customer").Elements("CompanyName")
customers.Elements("Customer").Elements("CompanyName")
Existují podobné paralely pro každou osu XPath.
Osa XPath | Osa LINQ to XML |
---|---|
podřízený (výchozí osa) | XContainer.Elements |
Nadřazený objekt (..) | XObject.Parent |
Osa atributu (@) | XElement.Attribute nebo XElement.Attributes |
osa předků | XNode.Ancestors |
Osa nadřazeného nebo vlastního původu | XElement.AncestorsAndSelf |
osa potomků (//) | XContainer.Descendants nebo XContainer.DescendantNodes |
potomků nebo samoobsluhod | XElement.DescendantsAndSelf nebo XElement.DescendantNodesAndSelf |
sledování na stejné | XNode.ElementsAfterSelf nebo XNode.NodesAfterSelf |
předchozí nástavbový | XNode.ElementsBeforeSelf nebo XNode.NodesBeforeSelf |
Následující | Žádný přímý ekvivalent. |
Předchozí | Žádný přímý ekvivalent. |