Compartir a través de


Comparación de XPath y LINQ to XML

XPath y LINQ to XML son similares de cierto modo. Ambos se pueden usar para consultar un árbol XML, devolviendo resultados como recopilación de elementos, recopilación de nodos o el valor de un elemento o atributo. Pero existen diferencias significativas entre las dos opciones.

Diferencias entre XPath y LINQ to XML

XPath no permite la proyección de nuevos tipos. Solo puede devolver recopilaciones de nodos del árbol, mientras que LINQ to XML puede ejecutar una consulta y proyectar un gráfico de objetos o un árbol XML en una nueva forma. Las consultas LINQ to XML hacen muchas más cosas que las expresiones XPath.

Las expresiones XPath existen de forma aislada en una cadena. El compilador de C# no puede ayudar a analizar la expresión XPath en tiempo de compilación. Por el contrario, el compilador de C# analiza y compila las consultas de LINQ to XML. El compilador puede detectar muchos errores de consulta.

Los resultados de XPath no están fuertemente tipados. En varias circunstancias, el resultado de evaluar una expresión XPath es un objeto, y depende del desarrollador determinar el tipo adecuado y convertir el resultado según sea necesario. Por el contrario, las proyecciones de una consulta de LINQ to XML están fuertemente tipadas.

Ordenación de los resultados

La recomendación XPath 1.0 indica que una recopilación que es el resultado de evaluar una expresión XPath está desordenada.

Pero cuando se recorre en iteración una recopilación devuelta por un método de eje XPath de LINQ to XML, los nodos de la recopilación se devuelven en el orden del documento. Esto es aplicable incluso cuando se tiene acceso a los ejes XPath donde se expresan los predicados en términos de orden de documento inverso, como preceding y preceding-sibling.

Por el contrario, la mayoría de los ejes de LINQ to XML devuelven las recopilaciones en el orden del documento. No obstante, dos de ellos, Ancestors y AncestorsAndSelf, devuelven las recopilaciones en el orden inverso del documento. En la siguiente tabla se enumeran los ejes y se indica el orden de la recopilación para cada uno:

Eje LINQ to XML Ordenación
XContainer.DescendantNodes Orden del documento
XContainer.Descendants Orden del documento
XContainer.Elements Orden del documento
XContainer.Nodes Orden del documento
XContainer.NodesAfterSelf Orden del documento
XContainer.NodesBeforeSelf Orden del documento
XElement.AncestorsAndSelf Orden del documento inverso
XElement.Attributes Orden del documento
XElement.DescendantNodesAndSelf Orden del documento
XElement.DescendantsAndSelf Orden del documento
XNode.Ancestors Orden del documento inverso
XNode.ElementsAfterSelf Orden del documento
XNode.ElementsBeforeSelf Orden del documento
XNode.NodesAfterSelf Orden del documento
XNode.NodesBeforeSelf Orden del documento

Predicados de posición

En una expresión XPath, los predicados de posición se expresan en términos de orden del documento para muchos ejes, pero se expresan en el orden del documento inverso para los ejes inversos, que son preceding, preceding-sibling, ancestor y ancestor-or-self. Por ejemplo, la expresión de XPath preceding-sibling::*[1] devuelve el elemento del mismo nivel inmediatamente anterior. Esto es aplicable aunque el conjunto de resultados finales se presenta en el orden del documento.

Por el contrario, todos los predicados de posición de LINQ to XML siempre se expresan en términos del orden del eje. Por ejemplo, anElement.ElementsBeforeSelf().ElementAt(0) devuelve el primer elemento secundario del elemento primario del elemento consultado, no el elemento del mismo nivel inmediatamente anterior. Otro ejemplo: anElement.Ancestors().ElementAt(0) devuelve el elemento primario.

Si quisiera buscar el elemento inmediatamente precedente de LINQ to XML escribiría la siguiente expresión:

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

Diferencias de rendimiento

Las consultas XPath que usan la funcionalidad de XPath en LINQ to XML serán más lentas que las consultas LINQ to XML.

Comparación de la composición

La composición de una consulta LINQ to XML es similar a la composición de una expresión XPath, aunque tiene una sintaxis muy diferente.

Por ejemplo, si tenemos un elemento de una variable con el nombre customers y queremos buscar un elemento inferior con el nombre CompanyName bajo todos los elementos secundarios con el nombre Customer, escribiríamos esta expresión XPath así:

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

La consulta equivalente de LINQ to XML es la siguiente:

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

Existen elementos similares para cada uno de los ejes XPath.

Eje XPath Eje LINQ to XML
secundario (el eje predeterminado) XContainer.Elements
Primario (..) XObject.Parent
eje de atributo (@) XElement.Attribute

o

XElement.Attributes
eje antecesor XNode.Ancestors
eje antecesor o propio XElement.AncestorsAndSelf
eje descendiente (//) XContainer.Descendants

o

XContainer.DescendantNodes
descendiente o propio XElement.DescendantsAndSelf

o

XElement.DescendantNodesAndSelf
siguientes-relacionados XNode.ElementsAfterSelf

o

XNode.NodesAfterSelf
precedentes-relacionados XNode.ElementsBeforeSelf

o

XNode.NodesBeforeSelf
siguientes No hay equivalente directo.
precedentes No hay equivalente directo.