Anteriormente, ya había tratado de manera introductoria la importante e innovadora herramienta LINQ, miramos como hacer consultas con algunos operadores básicos, donde buscaba filtrar, agrupar y ordenar algunos datos, sin embargo, LINQ es un vasto conjunto de tecnologías que no se queda en solo hacer simples consultas como las nombradas anteriormente, por esta razón, en esta ocasión vamos a mirar un tema que puede ser de gran interés, me refiero a la integración de LINQ to XML.
LINQ to XML es una interfaz que cuenta con un enfoque actualizado y rediseñado para la programación con XML. Esta herramienta nos da un fácil acceso a las funcionalidades con las que contamos en LINQ, es decir, podemos hacer cualquier consulta y debido a que LINQ to XML se encuentra integrado en .NET Framework podemos depurar, verificar cuando nuestra aplicación se está compilando, hacer tipeo fuerte y muchas otras cosas más. Al contar con LINQ to XML, tareas que hacemos usualmente los desarrolladores cómo cargar documentos XML en memoria, realizar consultas y hasta modificar, resultan muy sencillo; de igual forma, otra función importante que nos trae esta API es que podemos guardar documentos XML existentes en memoria y serializarlos; gracias a esto nos evitamos la ardua y engorrosa tarea de aprender el lenguaje de consulta XML, que a fin de cuentas resulta ser algo complicado.
Bueno, saliendo un poco de lo teórico entremos a la parte practica que es lo más emocionante de esta herramienta. Para esto, es importante saber que el espacio de nombres con el que cuenta LINQ to XML, contiene 19 clases, entre ellas, XAttribute, XCData, XComment, XContainer, XDeclaration, XDocument, XElement, pero para esta ocasión utilizaré solo algunas para que se vayan introduciendo en esta increíble API de LINQ.
Comencemos…
Para iniciar con LINQ to XML voy a mostrar cómo se lee un documento XML usando LINQ. En este caso use la clase XDocument, la cual es la que representa el documento XML. A parte voy a colocar cual es mi resultado al compilar y ejecutar el código.
Resultado:
Como paso siguiente vamos a agregar un nuevo elemento o como se diría en el lenguaje LINQ to XML un nuevo nodo, para esto voy a agregar la clase XElement, esta clase representa un nodo del documento, además de la clase agrego el operador AddFirst, el cual me permitirá agregar el nodo “Grade” como primer elemento del documento.
Resultado:
Ahora quiero eliminar uno de los nodos creados anteriormente, conforme a programamos con los operadores de LINQ puedo hacerlo con LINQ to XML, es por tal razón que, para esta ocasión vamos a usar nuestra Expresión Lambda, la cual se encarga de hacer un filtrado en nuestro documento Students y mediante el operador Remove, eliminará el nodo especificado que para este caso será la dirección (Address).
Resultado:
Carga de archivos grandes usando LINQ to XML
En varias ocasiones tenemos archivos XML enormes, que posiblemente pesan 256 Mb o quizás más, la carga y consulta de estos archivos por lo general tanto para el sistema como para nosotros los desarrolladores resulta compleja y algo tediosa, ya que entre mas grande el archivo más será el uso de memoria y eso no resulta nada conveniente, es por esta razón que LINQ to XML nos ofrece un método que permite procesar archivos de gran tamaño con una marca de memoria muy pequeña.
La correcta ejecución de este método de transmisión dependerá de estos puntos:
■ Aplicar en proyectos donde el documento fuente se ejecute una sola vez para que los elementos se procesen en orden de documentos.
■ No se debe usar operadores que materialicen el origen de datos antes de pasar el primer elemento, porque de ser así la marca de memoria pequeña no se guardará. En su lugar se puede hacer uso de operadores de consulta básicos como Order By, ya que, mediante este operador, podemos iterar la fuente, hacer recopilación de datos, clasificación de estos y por último devolución del primer elemento de la secuencia.
Bueno, sabiendo un poco de teoría pasemos a observar un ejemplo donde se aplicará este método.
Primero tenemos nuestro archivo XML:
Después en C# realizamos este código, mediante el cual crearemos un método que me cree un Xnode desde XmlReader, con el propósito de analizar mi documento XML y que de esta forma nos proporcione un acceso rápido, directo y sin almacenamiento cache a mis datos XML. Todo esto se puede realizar ya que XmlReader usa pequeñas cantidades de memoria. Este método lo podremos usar para cuando deseemos escribir un método que nos devuelva una colección de nodos, para tener como respuesta nodo a nodo a medida que estos se van leyendo.
Creación de Árboles
En LINQ to XML podemos encontrar la Construcción Funcional, la cual es encargada de construir los árboles XML en una sola instrucción de manera sencilla y eficiente. Para esta construcción debemos tener en cuento el uso exclusivo de las firmas de los constructores XElement y XAttribute, ya que mediante estos podremos pasar tanto el contenido del elemento o el atributo como argumentos de constructor.
Tanto XElement como XAttribute podrán pasar n cantidad de elementos secundarios como se quiera, a razón de que estos constructores tienen la capacidad de recibir un número variable de argumentos, sin embargo, aquellos elementos secundarios podrán tener sus propios elementos secundarios y por ende cualquier elemento tendrá el poder de agregar los atributos que se deseen.
Bueno, lo anterior es algo enredado, por eso mostrare un paso a paso de como se hace un árbol XML.
Paso 1: Crearemos un XElement el cual tendrá un contenido básico y solo una llamada a método.
Así mismo podemos pasar cualquier tipo de contenido como objeto.
Paso 2: Vamos a crear un elemento que va a contener varios elementos secundarios, esto lo haremos solamente al pasar una instancia de la clase XElement para el argumento del contenido.
Paso 3: Crearemos un árbol completo extendiendo el contenido del ejercicio anterior.
Ya miramos como se realiza un árbol XML, pero seria bueno y de gran ayuda observar un ejemplo sencillo de árboles con la implementación de LINQ.
Como se puede observar nuestra consulta LINQ filtra las edades que son menores a 18 años mostrando el resultado como un árbol XML.
Por último, ya podemos detallarnos de la gran ventaja con la que cuenta LINQ to XML al integrase con LINQ. Debido a que nos permite escribir consultas en el documento XML en memoria para realizar las operaciones que deseemos ejecutar y además nos da la capacidad de usar resultados de consultas como parámetros para XElement, sin embargo, aunque la capacidad de consulta de LINQ to XML es similar en funcionalidad con XQuery la sintaxis si suele cambiar un poco. Aparte pudimos observar la gran ventaja que tenemos con LINQ to XML para procesar archivos XML con una huella de memoria pequeña usando la clase XmlReader, finalmente nos detallamos de la facilidad que tenemos para crear árboles XML con la firma de XElement.
Leonardo Pirajan
Consultor Técnico Junior
Attomo Essential Group S. A.