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. |