Modificación del árbol XML en memoria en comparación con la construcción funcional (LINQ to XML)

Modificar un árbol XML directamente es un enfoque tradicional para cambiar la forma de un documento XML. Una aplicación típica carga un documento en un almacén de datos como DOM o LINQ to XML; utiliza una interfaz de programación para insertar nodos, eliminar nodos o cambiar su contenido y, a continuación, guarda el XML en un archivo o lo transmite a través de una red.

LINQ to XML permite otro enfoque que es útil en muchos escenarios: la construcción funcional. La construcción funcional trata la modificación de datos como un problema de transformación en lugar de una manipulación detallada de un almacén de datos. Si puede tomar una representación de datos y transformarla eficientemente de una a otra, el resultado es el mismo que si ha tomado un almacén de datos y lo ha manipulado de alguna manera para que tome otra forma. Un aspecto fundamental del enfoque de construcción funcional es pasar los resultados de las consultas a los constructores XDocument y XElement.

En muchos casos puede escribir el código de transformación en una fracción del tiempo que tardaría en manipular el almacén de datos y el código resultante es más eficaz y fácil de mantener. En esos casos, aunque el enfoque de transformación puede necesitar más potencia de procesamiento, es una forma más efectiva de modificar datos. Si un desarrollador está familiarizado con el enfoque funcional, el código resultante en muchos casos es más fácil de entender y resulta sencillo encontrar el código que modifica cada parte del árbol.

El enfoque en el que se modifica un árbol XML directamente es mucho más familiar para muchos programadores de DOM, mientras que el código escrito usando el enfoque funcional puede ser poco familiar para un desarrollador que aún no comprende este enfoque. Si solo tiene que realizar una pequeña modificación en un árbol XML grande, el enfoque en el que se modifica un árbol directamente en muchos casos consumirá menos tiempo de CPU.

En este artículo se proporcionan ejemplos de ambos enfoques. Suponga que desea modificar el siguiente documento XML sencillo para que los atributos se conviertan en elementos:

<?xml version="1.0" encoding="utf-8" ?>
<Root Data1="123" Data2="456">
  <Child1>Content</Child1>
</Root>

En el primero de los ejemplos siguientes se usa el enfoque tradicional de modificación directa y el segundo usa el enfoque de construcción funcional.

Ejemplo: Transformación de atributos en elementos con el enfoque tradicional directo

Puede escribir código de procedimientos para crear elementos a partir de atributos y después eliminar los atributos de la siguiente manera:

XElement root = XElement.Load("Data.xml");
foreach (XAttribute att in root.Attributes()) {
    root.Add(new XElement(att.Name, (string)att));
}
root.Attributes().Remove();
Console.WriteLine(root);
Dim root As XElement = XElement.Load("Data.xml")
For Each att As XAttribute In root.Attributes()
    root.Add(New XElement(att.Name, att.Value))
Next
root.Attributes().Remove()
Console.WriteLine(root)

Este ejemplo produce el siguiente resultado:

<Root>
  <Child1>Content</Child1>
  <Data1>123</Data1>
  <Data2>456</Data2>
</Root>

Ejemplo: Transformación de atributos en elementos con el enfoque de construcción funcional

Por el contrario, un enfoque funcional consta de un código para formar un nuevo árbol, eligiendo y seleccionando elementos y atributos del árbol de origen y transformándolos, según convenga, a medida que se agregan al nuevo árbol.

XElement root = XElement.Load("Data.xml");
XElement newTree = new XElement("Root",
    root.Element("Child1"),
    from att in root.Attributes()
    select new XElement(att.Name, (string)att)
);
Console.WriteLine(newTree);
Dim root As XElement = XElement.Load("Data.xml")
Dim newTree As XElement = _
    <Root>
        <%= root.<Child1> %>
        <%= From att In root.Attributes() _
            Select New XElement(att.Name, att.Value) %>
    </Root>
Console.WriteLine(newTree)

Este ejemplo produce el mismo XML que el primer ejemplo. No obstante, tenga en cuenta que puede ver realmente la estructura resultante del nuevo XML en el enfoque funcional. Puede ver la creación del elemento Root, el código que extrae el elemento Child1 del árbol de origen y el código que transforma los atributos del árbol de origen a los elementos del nuevo árbol.

El ejemplo funcional en este caso no es ni más corto ni más sencillo que el primer ejemplo. No obstante, si tiene muchos cambios que realizar a un árbol XML, el enfoque basado en procedimientos se hará más complejo y difícil de entender. Por el contrario, cuando se usa el enfoque funcional, se sigue formando el XML deseado, incrustando consultas y expresiones según convenga, para extraer el contenido deseado. El enfoque funcional produce código que es más fácil de mantener.

Tenga en cuenta que el enfoque funcional probablemente no tendrá un rendimiento tan bueno como la manipulación del árbol. El principal problema es que el enfoque funcional crea objetos de corta duración. No obstante, la compensación es efectiva si el uso del enfoque funcional permite una mayor productividad del programador.

Éste es un ejemplo muy sencillo, pero sirve para mostrar la diferencia de filosofía entre los dos enfoques. El enfoque funcional ofrece mayores ganancias de productividad para transformar documentos XML de gran tamaño.