Comparação XPath e de LINQ to XML
XPath e LINQ to XML são semelhantes em alguns aspectos. Ambos podem ser usados para ver uma árvore XML, retornando resultados como uma coleção de elementos, uma coleção de atributos, uma coleção de nós, ou o valor de um elemento ou de um atributo. Contudo, há diferenças significativas entre as duas opções.
Diferenças entre o XPath e o LINQ to XML
O XPath não permite a projeção de novos tipos. Somente é possível retornar coleções de nós de árvore, enquanto o LINQ to XML pode executar uma consulta e projetar um grafo de objeto ou uma árvore XML em uma nova forma. Consultas LINQ to XML podem fazer muito mais do que expressões XPath.
As expressões XPath existem no isolamento dentro de uma cadeia de caracteres. O compilador do C# não pode ajudar a analisar a expressão XPath em tempo de compilação. Por outro lado, as consultas do LINQ to XML são analisadas e compiladas pelo compilador do C#. O compilador pode capturar muitos erros de consulta.
Os resultados do XPath não são fortemente tipados. Em inúmeras circunstâncias, o resultado para avaliar uma expressão XPath é um objeto, e cabe ao desenvolvedor determinar o tipo apropriado e converter o resultado, conforme necessário. Por outro lado, as projeções de uma consulta do LINQ to XML são fortemente tipadas.
Ordenação de resultado
A recomendação do XPath 1.0 declara que uma coleção resultante da avaliação de uma expressão XPath é não ordenada.
Entretanto, ao fazer iterações por uma coleção retornada por um método do eixo XPath do LINQ to XML, os nós na coleção são retornados na ordem do documento. Este é o caso mesmo quando acessando os eixos XPath onde os predicados são expressos em termos de ordem inversa de documento, como preceding
e preceding-sibling
.
Por outro lado, a maioria dos eixos do LINQ to XML retorna coleções na ordem de documento. No entanto, duas delas, Ancestors e AncestorsAndSelf, retornam coleções na ordem inversa de documento. A tabela a seguir enumera os eixos, e indica a ordem de coleção para cada:
O eixo LINQ to XML | Ordenando |
---|---|
XContainer.DescendantNodes | Ordem de documento |
XContainer.Descendants | Ordem de documento |
XContainer.Elements | Ordem de documento |
XContainer.Nodes | Ordem de documento |
XContainer.NodesAfterSelf | Ordem de documento |
XContainer.NodesBeforeSelf | Ordem de documento |
XElement.AncestorsAndSelf | Ordem inversa de documento |
XElement.Attributes | Ordem de documento |
XElement.DescendantNodesAndSelf | Ordem de documento |
XElement.DescendantsAndSelf | Ordem de documento |
XNode.Ancestors | Ordem inversa de documento |
XNode.ElementsAfterSelf | Ordem de documento |
XNode.ElementsBeforeSelf | Ordem de documento |
XNode.NodesAfterSelf | Ordem de documento |
XNode.NodesBeforeSelf | Ordem de documento |
Predicados posicionais
Em uma expressão XPath, os predicados posicionais são expressos em termos de pedido de documento para muitos eixos, mas expressos na ordem inversa de documento para os eixos invertidos. Os eixos inversos são: preceding
, preceding-sibling
, ancestor
e ancestor-or-self
. Por exemplo, a expressão XPath preceding-sibling::*[1]
retorna imediatamente antes o irmão. Este é o caso mesmo que o conjunto de resultados final é apresentado na ordem de documento.
Por outro lado, todos os predicados posicionais em LINQ to XML sempre são expressos em termos de pedido do eixo. Por exemplo, anElement.ElementsBeforeSelf().ElementAt(0)
retorna o primeiro elemento filho do pai do elemento consultado, não irmão anterior imediato. Outro exemplo: anElement.Ancestors().ElementAt(0)
retorna o elemento pai.
Se você desejar localizar imediatamente o elemento precedente no LINQ to XML, escreva a expressão a seguir:
ElementsBeforeSelf().Last()
ElementsBeforeSelf().Last()
Diferenças de desempenho
As consultas XPath que usam a funcionalidade do XPath no LINQ to XML não serão tão bem executadas como as consultas do LINQ to XML.
Comparação de composição
A composição de uma consulta do LINQ to XML é similar à composição de uma expressão XPath, mas a sintaxe é muito diferente.
Por exemplo, caso tenha um elemento em uma variável nomeada como customers
e você queira localizar um elemento de neto nomeado como CompanyName
em todos os elementos filho nomeados como Customer
, escreva uma expressão XPath como segue:
customers.XPathSelectElements("./Customer/CompanyName")
customers.XPathSelectElements("./Customer/CompanyName")
A consulta do LINQ to XML equivalente é:
customers.Elements("Customer").Elements("CompanyName")
customers.Elements("Customer").Elements("CompanyName")
Há paralelas semelhantes para cada um dos eixos XPath.
O eixo XPath | O eixo LINQ to XML |
---|---|
o eixo filho (padrão) | XContainer.Elements |
Pai (.). | XObject.Parent |
o eixo de atributo (@) | XElement.Attribute ou XElement.Attributes |
o eixo de ancestral | XNode.Ancestors |
o eixo de antepassado-ou- auto | XElement.AncestorsAndSelf |
o eixo descendente (/) | XContainer.Descendants ou XContainer.DescendantNodes |
descendente-ou-auto | XElement.DescendantsAndSelf ou XElement.DescendantNodesAndSelf |
seguir-irmão | XNode.ElementsAfterSelf ou XNode.NodesAfterSelf |
acima-irmão | XNode.ElementsBeforeSelf ou XNode.NodesBeforeSelf |
após | Nenhum equivalente direto. |
precedência | Nenhum equivalente direto. |