Windows Phone. Leer un RSS.

Introducción

Una fuente de datos muy común en una aplicación móvil suele ser meduante una fuente RSS. RSS (Really Simple Syndication), es un formato XML utilizado normalmente para  compartir contenidos en la web.

HttpWebRequest vs WebClient. Fight!

Tenemos dos opciones para poder obtener los datos de la fuente RSS:

  • WebClient.
  • HttpWebRequest.

Vale, ¿cual usar?

WebClient es un wrapper de la clase HttpWebRequest utilizado para realizar peticiones web. La gran ventaja de la clase WebClient es que es fácil de usar (muy pocas líneas). Sin embargo, como contra el proceso lo realiza en el hilo de la interfaz congelando la misma mientras está procesando.

HttpWebRequest realiza la petición en un hilo separado sin bloquear la interfaz. Debemos ser nosotros quien pasemos los datos obtenidos a la interface de usuario. Por contra, necesita más líneas para obtener el mismo resultado pero la ventaja de trabajar en un hilo aparte es suficiente como para que sea el método más utilizado para obtener datos de una fuente RSS.

Para que quede todo más claro veamos un ejemplo rápido:

  • Utilizando WebClient:
var cliente = new WebClient();
cliente.DownloadStringCompleted += (s, ev) => { responseTextBlock.Text = ev.Result; };
cliente.DownloadStringAsync(new Uri("https://javiersuarezruiz.wordpress.com/feed/"));
  • Utilizando HttpWebRequest:
var request = (HttpWebRequest)WebRequest.Create(
                new Uri("https://javiersuarezruiz.wordpress.com/feed/"));
request.BeginGetResponse(r =>
{
    var httpRequest = (HttpWebRequest)r.AsyncState;
    var httpResponse = (HttpWebResponse)httpRequest.EndGetResponse(r);

    using (var reader = new StreamReader(httpResponse.GetResponseStream()))
    {
        var response = reader.ReadToEnd();

        //Interfaz de Usuario
        Deployment.Current.Dispatcher.BeginInvoke(new Action(() =>
            {
                TextBlock.Text = response;
            }));
    }
}, request);

Como de costumbre, vamos a realizar un ejemplo práctico. Creamos un nuevo proyecto:

La plantilla seleccionada será “Windows Phone Application” para simplificar al máximo el ejemplo. El objetivo del ejemplo será poder leer el RSS del blog que es el siguiente:

https://javiersuarezruiz.wordpress.com/feed/

Vamos a utilizar la clase HttpWebRequest para obtener el RSS. Recordar que la petición se realizará en segundo plano:

private void ObtenerDatos()
{
     var request = (HttpWebRequest)WebRequest.Create(
     new Uri("https://javiersuarezruiz.wordpress.com/feed/"));
     request.BeginGetResponse(r =>
     {
          var httpRequest = (HttpWebRequest)r.AsyncState;
          var httpResponse = (HttpWebResponse)httpRequest.EndGetResponse(r);

          using (var reader = new StreamReader(httpResponse.GetResponseStream()))
          {
               var response = reader.ReadToEnd();

               //Interfaz de Usuario
               Deployment.Current.Dispatcher.BeginInvoke(new Action(() =>
               {
                    LeerDatos(response);
               }));
          }
     }, request);
}

Utilizamos el método Create de la clase HttpWebRequest para inicializar el objeto. A continuación, utilizamos el método BeginGetResponse (fijaos que es un método asíncrono) donde realizamos la llamada para obtener los datos.

Importante. Fijaos como debemos utilizar un Dispatcher para poder pasar los datos al hilo principal de ejecución de la aplicación, donde pasamos la información almacenada en la variable response a un método llamado LeerDatos (no os preocupéis por el método, lo analizaremos a continuación).

Antes de continuar, debemos crear una pequeña clase en nuestro proyecto que define todas las propiedades que deseamos obtener del RSS:

public class RSSItem
{
     public string Titulo { get; set; }
     public string Contenido { get; set; }
     public string Fecha { get; set; }
}

Nuestro método ObtenerDatos ha obtenido toda la información de la fuente RSS y ha pasado la información a otro método en el hilo principal de ejecución llamado LeerDatos. Vamos a analizar ese método:

private void LeerDatos(string rss)
{
     XDocument documento = XDocument.Parse(rss);

     List<RSSItem> items = (from item in documento.Descendants("item")
     select new RSSItem
     {
          Titulo = item.Element("title").Value,
          Contenido = item.Element("description").Value,
          Fecha = item.Element("pubDate").Value
     }).ToList();
}

Tras descargar los datos con la clase HttpWebRequest (un archivo XML) debemos lograr extraer la información que deseamos y almacenarla en objetos del tipo RSSItem (recordar la clase que hemos creado anteriormente).

¿Cómo lo conseguimos?

Una de las opciones posibles es utilizar LINQ to XML. Es la forma más común hoy día y será el método utilizado. LINQ to XML proporciona una interfaz de programación XML en memoria que aprovecha las características de LINQ. Nos basaremos en el uso de una clase llamada XDocument. Para poder utilizarla debemos añadir la siguiente referencia al proyecto:

System.Xml.Linq.dll

Utilizamos el método Parse de la clase XDocument pasandole la información obtenida. De esta forma logramos un documento XML con el que podemos trabajar utilizando LINQ to XML. Buscamos todos los nodos de tipo “item” existentes y vamos creando un nuevo objeto RSSItem al que le asignamos sus propiedades principales.

Continuamos. Hemos obtenido la información que necesitamos y hemos creado una colección de objetos RSSItem con ella. Aún no hemos realizado ningún cambio en la interfaz. Dado que tenemos una colección de objetos, vamos a utilizar un control Listbox para representarla visualmente:

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
     <ListBox x:Name="lstRss">
     </ListBox>
</Grid>

Tras agregar el control debemos definir la estructura visual de cada elemento de la lista. Lo conseguiremos modificando el ItemTemplate del ListBox:

<ListBox x:Name="lstRss">
     <ListBox.ItemTemplate>
          <DataTemplate>
               <StackPanel VerticalAlignment="Top">
                    <TextBlock FontSize="28" TextWrapping="Wrap" Margin="12,0,0,0" HorizontalAlignment="Left" Foreground="White" Text="{Binding Titulo}" />
                    <TextBlock Foreground="{StaticResource PhoneSubtleBrush}" Margin="12,0,0,10" Text="{Binding Fecha}" />
               </StackPanel>
          </DataTemplate>
     </ListBox.ItemTemplate>
</ListBox>

Por último, debemos enlazar nuestra colección de datos en memoria con nuestro control Listbox de la interfaz de usuario (utilizamos la propiedad ItemsSource del control):

lstRss.ItemsSource = items;

En este punto si compilamos y ejecutamos la aplicación veremos lo siguiente:

Puedes ver en video el resultado de nuestro ejemplo a continuación:

También puedes descargar el ejemplo realizado a continuación:

Conclusiones

Los pasos que hemos debido realizar han sido:

  • Obtener la información deseada. Hemos utilizado la clase HttpWebRequest para ello.
  • Procesar la información obtenida para lograr una lista de objetos que podamos enlazar con la interfaz de usuario. Linq to XML.
  • Enlazar los datos ya procesados con la interfaz.

Si os surgen dudas o sugerencias podéis dejarlas en los comentarios.

Más información

17 pensamientos en “Windows Phone. Leer un RSS.

    • Buenas Javier,

      De entrada, muchas gracias!. Me alegro de que la entrada te haya sido de utilidad. En cuanto a lo que mencionas, ¿te refieres a una vez seleccionado un elemento de la lista navegar y mostrar una página de detalles?. Si es así, no tengo ningún tutorial escrito ahora mismo, pero tomo nota.

      Mientras tanto te recomiendo echarle un vistazo a un ejemplo de lector RSS disponible en Nokia Developer: http://www.developer.nokia.com/Develop/Windows_Phone/Code_examples/

      Un saludo.

      • Muchas Gracias, me pondré a revisar a fondo el ejemplo que me has mandado.

        Creo que no me supe explicar, que si existe la manera de poder ver leer la noticia completa que aparece en el RSS.

        Por cierto gran Blog, me ha servido mucho en el desarrollo de Apps. Sigue así.

      • Gracias a ti por leer el blog!

        En cuanto a tu pregunta, si, se puede hacer lo que quieres (salvo que el RSS no contenga toda la información que deseas). Lo anoto como futura entrada. Si te urge, intentaré hacerte un ejemplo pequeño que te sea válido.

        Un saludo.

  1. Me podrias ayudar a como sacar el link para q lo pueda mostrar en otra pantalla y en el navegador es q no se como sacar el dato o bien en su defecto como lo dice el compañero Javier como leo la noticia completta en otra pantalla, mi idea era mostrar otra pantalla y mostrala en un navegador pero no ce, agadeceria la ayuda

      • gracias Javier! tengo una consulta… ¿como puedo obtener los datos de un enclosure? lo que pasa es que en la etiqueta enclosure hay una url de una foto que quiero obtener pero no logro accesar a ella no se si me entiendes, espero que si. te lo agradezco mucho saludos

      • Hola Felipe,

        Si creo que te he entendido. Tienes algo asi:

        enclosure url=”http://www.test.com/image.jpg ” length=”5000″ type=”image/jpge”

        ¿Cierto?

        Puedes acceder con LINQ to Xml asi:

        var element = pElement.Element(“enclosure”);
        if (element != null)
        {
        foreach (var xAttribute in element.Attributes())
        {
        if (xAttribute.Name == “url”)
        {
        item.Image = xAttribute.Value;
        break;
        }
        }
        }

        Espero que te haya sido de utilidad. Podría ser interesante escribir un artículo con Tips and Tricks para acceder a ciertos elementos o parsear ciertos RSS. Tomo nota.

        Un saludo.

  2. hola nuevamente me ayudaste mucho logre obtener el contenido de enclosure! pero me salio otro problema, te pregunto por que eres experto y necesito ayuda. lo que pasa es que ahora necesito obtener el contenido de un , te agradezco mucho gracias perdon por tantas preguntas saludos

      • hola gracias por responder el mensaje no se por que se corto pero creo que ya lo solucioné el problema era obtener el contenido de un content:encoded, tenia que agregar el namespace de content para poder leerlo gracias nuevamente saludos

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s