Design a site like this with WordPress.com
Get started

Usando LINQ to XML (y como crear un lector de RSS con él)

Probablemente la mayor mejora en el modelo de programación que se ha hecho en .NET 3.5 es el trabajo que la consulta de datos sea un concepto de primera clase. Llamamos a este modelo de programación de consultas “LINQ”, que viene de .NET Language Integrated Query.

LINQ permite un modelo realmente rico que facilita la creación de diferentes proveedores de datos. .NET3.5 integra un conjunto de librerías que permiten realizar consultas LINQ sobre objetos, xml y bases de datos.

¿Qué es LINQ to XML?

LINQ to XML es un proveedor de datos de LINQ que está implementado en el namespace “System.Xml.Linq” en .NET 3.5

Proporciona un modelo de programación limpio que nos permite leer, construir y escribir datos en XML. Con esto, podemos realizar consultas LINQ a través de XML que tengamos en el sistema de archivos, desde una URL remota o servicio web, o cualquier contenido XML en memoria.

Nos permite una forma de consultar datos y formarlos mucho más fácilmente que con la API de bajo nivel XmlReader/XmlWriter. También es mucho más eficiente (y usa mucha menos memoria) que la API DOM que tiene XmlDocument.

Usando LINQ to XML para consultar un archivo XML local

Para una primera toma de contacto y ver cómo funciona LINQ to XML, podemos crear un archivo local XML simple  como el siguiente, que usa un schema personalizado que hemos definido para guardar nuestras rss:

Podríamos usar la nueva clase XDocument que viene en el namespace System.Xml.Linq para abrir y consultar el archivo. Lo que queremos es filtrar los elementos <Feed> y devolver una secuencia de las feeds deshabilitadas (esto es, cuando el elemento <Feed> tenga el atributo “status” con el valor “disable”). Con el siguiente código lo conseguimos:

VB:

C#:

Fijáos en el código que estamos cargando el archivo XML con el método estático XDocument.Load(path) – que devuelve un objeto XDocument. Como estamos ejecutando este codigo en ASP.NET, usamos el método Server.MapPath(path) para obtener la ruta correcta de nuestro archivo XML relativo a la página que estamos ejecutando.

Una vez que tenemos el objecto XDocument podemos escribir la expresión LINQ necesaria para obtener los datos que estamos buscando. En el código anterior estamos consultado cada elemento <Feed> del archivo XML. Esto lo conseguimos con la consulta:

from feed in feedXML.Decedents(“Feed”)

Luego le aplicamos un filtro para que devuelva aquellos elementos “Feed” que no tienen el atributo “status” y los que cuyo valor del atributo “status” NO es “disabled”:

Where (feed.Attribute(“status”) is Nothing) OrElse (feed.Attribute(“status”).Value <> “disabled”)

Ahora usamos el select de nuestra consulta LINQ para indicar qué datos queremos devolver. Simplemente escribimos “select feed”, LINQ to XML devolverá una secuencia de objetos XElement que representan cada nodo del archivo XML que cumplen el filtro. En el código anterior usamos las características de shaping/projection de LINQ en lugar de definir un nuevo tipo anónimo al vuelo, y definimos dos propiedades – Name y Feed – que queremos obtener con los subelementos <Name> y <URL> de cada elemento <Feed>:

Select Name = feed.Element(“Name”).Value, Url=feed.Element(“Url”).Value

Y ahora podemos trabajar con esa colección de datos como lo haríamos con cualquier colección o tabla en .NET. VS 2008 nos da intellisense y chequeo en compilación sobre esta secuencia de  tipos anónimos:

También podemos enlazar estos resultados con cualquier control de ASP.NET, Windows Forms, o WPF. Por ejemplo, si tenemos un control de lista desplegable (dropdownlist) en nuestra página:

Podemos usar el código de LINQ to XML anterior para enlazar los resultados:

Con esto, nuestra página quedará de la siguiente forma:

Umm- ¿que es eso de “tipos anonimos”?

En el código anterior hemos usado una nueva característica de VB y C# llamada “tipo anónimos”. Los tipos anónimos permiten a los desarrolladores definir tipos directamente en una linea, sin tener que crear una clase para el tipo. Podéis aprender más sobre ellos en el post sobre los tipos anónimos.

Aunque los tipos anónimos son muy útiles cuando queremos iterar localmente y trabajar con datos, normalmente queremos/necesitamos definir clases cuando pasamos los resultados de las consultas LINQ entre múltiples clases, entre librerías, y entre servicios web.

Para permitir esto, podemos definirnos una clase llamada “FeedDefinition” para representar nuestros datos así:

Fijáos que estamos usando la característica de “Propiedades automáticas” de C# para definir las propiedades (sin tener que definir una variable para ellos).

Ahora podemos escribir el siguiente método para devolver una lista genérica List<FeedDefinition>:

Fijáos que el único cambio que hemos hecho a la consulta LINQ to XML es que en vez de usar un tipo anónimo (“select new” sin ningún tipo) hemos usado “select new FeedDefinition”. Con este cambio estamos devolviendo una secuencia de objetos FeedDefinition que podemos pasar a otras clases, ensamblados, o a servicios web.

Usar LINQ to XML para obtener una lista de rss en XML remota

El método estático XDocument.Load(path) nos permite abrir tanto archivos XML locales, como feeds XML devueltas de una url HTTP. Esto nos permite acceder a RSS remotas, REST APIs, y a cualquier otro contenido XML publicado en la web.

Por ejemplo, veamos el XML de las rss de mi blog(http://weblogs.asp.net/scottgu/rss.aspx):

Con el siguiente código LINQ to XML podemos obtener los datos de mi RSS, y trabajar con cada elemento feed individual como cualquier otro objeto .NET:

Fijáos cómo estamos convirtiendo el campo “Published” de la rss – que es un string en XML- a un tipo DateTime de .NET. Fijáos también que LINQ to XML añade un tipo XNamespace que nos permite una forma segura de tipos para declarar y trabajar con Namespaces XML ( Lo que necesitamos hacer para obtener los elementos <slash:comments>).

Podemos aprovechar las características de composición de LINQ para hacer otra consulta más para obtener aquellos post que han sido publicados en los últimos siete días:

Como vemos, podemos usar los resultados de una consulta LINQ como parte de entrada de otra. Con esto conseguimos un código muy limpio, y entendible.

Usar subconsultas LINQ dentro de una expresión LINQ to XML

Si miramos el XML del RSS, veremos que el tag de comentarios de cada post se guardan como elementos <category> repetidos debajo de cada elemento <item>:

Cuando definimos el modelo de objetos para una clase “BlogEntry”, podemos representar los valores de <category> como una colección de strings. Por ejemplo, con una propiedad “Tags” que es una lista genérica de strings:

Os estaréis preguntando – ¿Como obtenemos el conjunto de elementos <category> de los elementos <item> y los transformamos en una colección de strings?. LINQ permite que este tipo de escenarios sea muy sencillo, con consultas LINQ anidadas:

LINQ nos permite coger grandes cantidades de datos y hacerlas jerárquicas (y tomar una estructura de datos jerárquica y llenarla). Podemos usar esta característica con cualquier tipo de fuente de datos – XML, SQL, objetos, arrays, colecciones, etc.

Juntarlo todo para un lector simple de RSS

Ya hemos visto lo sencillo que es escribir código LINQ to XML para obtener una RSS de un archivo local, y cómo consultarla remotamente para obtener los detalles de cada elemento. Podemos enlazar el resultado a un GridView o ListView de ASP.NET:

Hemos construido una aplicación de ejemplo que junta todas esas características para obtener un lector de RSS con LINQ to XML y el nuevo control <asp:ListView>. Podéis descargarla de aquí. Está tanto en VB como en C#.

Resumen

LINQ to XML es una herramienta muy potente para consultar, filtrar y transformar datos XML de forma eficiente. Podemos usarlo tanto para XML’s locales o remotos. Podemos usarlo para transformar datos XML en objetos y colecciones .NET que podremos manipular y transferir en nuestras aplicaciones.

LINQ to XML usa el mismo núcleo y conceptos sobre consultas de LINQ, que LINQ to SQL, LINQ to Object, LINQ to SharePoint, LINQ to Amazon, LINQ to NHibernate, etc, usan cuando consultan datos. Podéis aprender más sobre la sintaxis de LINQ y las nuevas características de VB y C# en los siguientes post:

También encontraréis útil la serie de post sobre LINQ to SQL:

Dentro de poco volveremos con LINQ to XML y veremos cómo podemos usarlo no sólo para datos XML sino para generar cualquier tipo de salida XML desde una estructura de datos de .NET.

Espero que sirva

Scott.

Traducido por: Juan María Laó Ramos. Microsoft Student Partner.

toH tlhIngan Hol DajatlhlaH ‘e’ DaneH’a’?

Author: Juanma

Bueno, como reza el título de este blog y de las cosas que iré escribiendo ya os hareis una idea de cómo soy.

9 thoughts on “Usando LINQ to XML (y como crear un lector de RSS con él)”

  1. Una consulta, como puedo aplicar esta en un blog en BLOGGER O BLOGSPOT , ITEM CAMBIA POR ENTRY . LE GARDECIRIA SI ALGUIEN ME PUEDE DAR UNA MANO CON ESTO.
    COPIO LA RSS

    tag:blogger.com,1999:blog-7774657182171563008
    2012-05-06T14:33:57.375-07:00

    Cocco Marcela

    Cocco Marcela
    noreply@blogger.com

    Blogger
    1
    1
    25

    tag:blogger.com,1999:blog-7774657182171563008.post-6452100713817887013
    2012-05-06T14:28:00.000-07:00
    2012-05-06T14:33:57.379-07:00

    Proyecto “Hola Mundo 2.0”
    <br /><a name=’more’></a>Tratando de romper el mito “En Casa de Herrero Cuchillo de Palo”Llevo aproximadamente 6 años desarrollando con tecnologías .NET  y en este tiempo  no he publicado ningún trabajo.Este proyecto viene a ser una especie de portfolio tardío, pero no para contar lo que he aprendido  y hecho en este tiempo sino  para  utilizar  y aprender nuevas tecnologías en un proceso:1)Investigar2)Aprender3)Aplicar4)Enseñar5)Compartir<br />

    Cocco Marcela
    noreply@blogger.com

    0

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: