Partilhar via


Comparação de XPath e LINQ com XML

XPath e LINQ to XML são semelhantes em alguns aspetos. Ambos podem ser usados para consultar 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 atributo. No entanto, existem diferenças significativas entre as duas opções.

Diferenças entre XPath e LINQ to XML

XPath não permite projeção de novos tipos. Ele só pode retornar coleções de nós da árvore, enquanto o LINQ to XML pode executar uma consulta e projetar um gráfico de objeto ou uma árvore XML em uma nova forma. As consultas LINQ to XML podem fazer muito mais do que expressões XPath.

As expressões XPath existem isoladamente dentro de uma cadeia de caracteres. O compilador C# não pode ajudar a analisar a expressão XPath em tempo de compilação. Por outro lado, as consultas LINQ to XML são analisadas e compiladas pelo compilador C#. O compilador pode capturar muitos erros de consulta.

Os resultados do XPath não são fortemente digitados. Em várias circunstâncias, o resultado da avaliação de uma expressão XPath é um objeto, e cabe ao desenvolvedor determinar o tipo adequado e lançar o resultado conforme necessário. Por outro lado, as projeções de uma consulta LINQ to XML são fortemente tipadas.

Ordenação de resultados

A Recomendação XPath 1.0 afirma que uma coleção que é o resultado da avaliação de uma expressão XPath não está ordenada.

No entanto, ao iterar através de uma coleção retornada por um método de eixo LINQ to XML XPath, os nós na coleção são retornados na ordem do documento. Este é o caso mesmo ao acessar os eixos XPath onde os predicados são expressos em termos de ordem inversa do documento, como preceding e preceding-sibling.

Por outro lado, a maioria dos eixos LINQ to XML retorna coleções na ordem do documento. No entanto, dois deles, Ancestors e AncestorsAndSelf, devolvem coleções em ordem inversa de documentos. A tabela a seguir enumera os eixos e indica a ordem de coleta para cada um:

Eixo LINQ to XML Ordenação
XContainer.DescendantNodes Ordem de documentos
XContainer.Descendentes Ordem de documentos
XContainer.Elements Ordem de documentos
XContainer.Nodes Ordem de documentos
XContainer.NodesAfterSelf Ordem de documentos
XContainer.NodesBeforeSelf Ordem de documentos
XElement.AncestorsAndSelf Ordem inversa do documento
XElement.Attributes Ordem de documentos
XElement.DescendantNodesAndSelf Ordem de documentos
XElement.DescendentesAndSelf Ordem de documentos
XNode.Ancestrais Ordem inversa do documento
XNode.ElementsAfterSelf Ordem de documentos
XNode.ElementsBeforeSelf Ordem de documentos
XNode.NodesAfterSelf Ordem de documentos
XNode.NodesBeforeSelf Ordem de documentos

Predicados posicionais

Dentro de uma expressão XPath, os predicados posicionais são expressos em termos de ordem do documento para muitos eixos, mas são expressos em ordem inversa do documento para eixos reversos. Os eixos inversos são: preceding, preceding-sibling, ancestor, e ancestor-or-self. Por exemplo, a expressão preceding-sibling::*[1] XPath retorna o irmão imediatamente anterior. Este é o caso, embora o conjunto de resultados finais seja apresentado por ordem documental.

Por outro lado, todos os predicados posicionais em LINQ to XML são sempre expressos em termos da ordem do eixo. Por exemplo, anElement.ElementsBeforeSelf().ElementAt(0) retorna o primeiro elemento filho do pai do elemento consultado, não o irmão imediatamente anterior. Outro exemplo: anElement.Ancestors().ElementAt(0) retorna o elemento pai.

Se você quisesse encontrar o elemento imediatamente anterior em LINQ to XML, você escreveria a seguinte expressão:

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

Diferenças de desempenho

As consultas XPath que usam a funcionalidade XPath no LINQ to XML serão mais lentas do que as consultas LINQ to XML.

Comparação da composição

A composição de uma consulta LINQ to XML é semelhante à composição de uma expressão XPath, mas a sintaxe é muito diferente.

Por exemplo, se você tiver um elemento em uma variável chamada customers, e quiser encontrar um elemento neto nomeado CompanyName sob todos os elementos filho nomeados Customer, você escreveria esta expressão XPath:

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

A consulta LINQ equivalente a XML é:

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

Existem paralelos semelhantes para cada um dos eixos XPath.

Eixo XPath Eixo LINQ to XML
filho (o eixo padrão) XContainer.Elements
Pai (..) XObject.Parent
eixo do atributo (@) XElement.Attribute

ou

XElement.Attributes
eixo ancestral XNode.Ancestors
eixo ancestral-ou-si mesmo XElement.AncestorsAndSelf
eixo descendente (//) XContainer.Descendants

ou

XContainer.DescendantNodes
descendente-ou-si mesmo XElement.DescendantsAndSelf

ou

XElement.DescendantNodesAndSelf
irmão-seguinte XNode.ElementsAfterSelf

ou

XNode.NodesAfterSelf
irmão-anterior XNode.ElementsBeforeSelf

ou

XNode.NodesBeforeSelf
a seguir Sem equivalente direto.
Precedentes Sem equivalente direto.