XMLSerializer y XML Attributes

Debido a la gran cantidad de información externa que debemos tratar en nuestras aplicaciones y la gran necesidad de llegar a un acuerdo de comunicación entre distintas tecnologías, hoy me gustaría mostrar cómo es posible pasar información XML a objetos en .NET de una forma eficiente y automática.

Para mostrar un ejemplo que está a la orden del día, he recuperado uno de mis estados de Twitter en formato XML desde su API para poder tratarlo y montar algunos de sus elementos en los objetos de mi aplicación.

<?xml version="1.0" encoding="UTF-8"?>
<status>
  <created_at>Mon May 24 17:24:07 +0000 2010</created_at>
  <id>14636452344</id>
  <text>Status en XML</text>
  <source>&lt;a href=&quot;http://apiwiki.twitter.com/&quot; rel=&quot;nofollow&quot;&gt;API&lt;/a&gt;</source>
  <truncated>false</truncated>
  <in_reply_to_status_id></in_reply_to_status_id>
  <in_reply_to_user_id></in_reply_to_user_id>
  <favorited>false</favorited>
  <in_reply_to_screen_name></in_reply_to_screen_name>
  <user>
    <id>51491702</id>
    <name>Gisela Torres</name>
    <screen_name>0GiS0</screen_name>
    <location>Madrid (Spain)</location>
    <description>ASP.NET, ASP.NET MVC, JQuery,C#, NHibernate, Windows Azure</description>
    <profile_image_url>http://a1.twimg.com/profile_images/881811810/Picture_7_normal.jpg</profile_image_url>
    <url>http://geeks.ms/blogs/gtorres/</url>
    <protected>false</protected>
    <followers_count>235</followers_count>
    <profile_background_color>C6E2EE</profile_background_color>
    <profile_text_color>663B12</profile_text_color>
    <profile_link_color>1F98C7</profile_link_color>
    <profile_sidebar_fill_color>DAECF4</profile_sidebar_fill_color>
    <profile_sidebar_border_color>C6E2EE</profile_sidebar_border_color>
    <friends_count>105</friends_count>
    <created_at>Sat Jun 27 17:04:48 +0000 2009</created_at>
    <favourites_count>0</favourites_count>
    <utc_offset>3600</utc_offset>
    <time_zone>Madrid</time_zone>
    <profile_background_image_url>http://a1.twimg.com/profile_background_images/60722374/free_twitter_designer.jpg</profile_background_image_url>
    <profile_background_tile>false</profile_background_tile>
    <notifications>false</notifications>
    <geo_enabled>false</geo_enabled>
    <verified>false</verified>
    <following>false</following>
    <statuses_count>1401</statuses_count>
    <lang>en</lang>
    <contributors_enabled>false</contributors_enabled>
  </user>
  <geo/>
  <coordinates/>
  <place/>
  <contributors/>
</status>

Si nos fijamos en la estructura que nos ofrece Twitter para representar un status, vemos que el elemento principal se trata del status en sí con una serie de elementos relacionados directamente con él y, como un conjunto, tenemos un elemento compuesto representando al usuario propietario de ese status. Como podéis imaginar podemos obtener claramente dos objetos bien diferenciados de esta respuesta de Twitter.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

namespace XMLSerializer
{
    [XmlType(TypeName = "status")]
    public class Status
    {
        [XmlElement("id")]
        public long Id { get; set; }

        [XmlElement("text")]
        public string Text { get; set; }

        [XmlElement("source")]
        public string Source { get; set; }

        [XmlElement("in_reply_to_status")]
        public int InReplyToStatus { get; set; }

        [XmlElement("user")]
        public User User { get; set; }
    }
}

Creamos una clase con un atributo del tipo XmlType que indica el nombre del miembro que vamos a almacenar en la misma. Decoramos cada una de sus propiedades con los valores correspondientes en su representación en XML. No es necesario seguir el mismo orden ni recuperar todos los elementos. Si nos fijamos en la propiedad User, vemos que hace referencia al elemento compuesto que vimos anteriormente y, además, que recibe y devuelve un objeto del tipo User declarado también en la aplicación.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

namespace XMLSerializer
{
    [XmlType(TypeName = "user")]
    public class User
    {
        [XmlElement("id")]
        public long Id { get; set; }

        [XmlElement("name")]
        public string Name { get; set; }

        [XmlElement("screen_name")]
        public string ScreenName { get; set; }

        [XmlElement("location")]
        public string Location { get; set; }
    }
}

Para comprobar que estas clases son compatibles con lo establecido en formato XML, podemos recuperarlo de la siguiente manera:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml.Serialization;

namespace XMLSerializer
{
    class Program
    {
        static void Main(string[] args)
        {
            var xml = File.ReadAllText("../../XMLs/Status.xml");

            var xmlSerializer = new XmlSerializer(typeof(Status));
            var reader = new StringReader(xml);
            var status = (Status)xmlSerializer.Deserialize(reader);

            Console.WriteLine("Status Id: {0}", status.Id);
            Console.WriteLine("Status text: {0}", status.Text);
            Console.WriteLine("Status source: {0}", status.Source);
            Console.WriteLine("Status in reply to status id: {0}", status.InReplyToStatus);
            Console.WriteLine("User Id: {0}", status.User.Id);
            Console.WriteLine("User name: {0}", status.User.Name);
            Console.WriteLine("User location: {0}", status.User.Location);
            Console.WriteLine("User screen name: {0}", status.User.ScreenName);
            Console.ReadLine();
        }
    }
}

En el caso de Twitter, y en general en todos aquellos recursos que estén relacionados entre sí, podemos conseguir de una forma rápida y a la vez productiva la unión de los distintos elementos que formarán una gran parte del dominio de la aplicación.

Espero que sea de utilidad.

¡Saludos!

4 comentarios sobre “XMLSerializer y XML Attributes

Deja un comentario