Guarda tus clases .NET en XML
Introducción al XmlSerializer

Fecha: 07/Mar/2003 (07/Mar/2003)
Autor: Juan M. Servera

 

Gracias a .NET persistir el estado de una clase es sumamente sencillo ya que nos provee de clases que harán casi todo el trabajo por nosotros.

 

XmlSerializer

La clase XmlSerializer nos permite guardar o recuperar una representación Xml de un objeto, pero para que pueda realizar su trabajo antes debemos conocer un poco sus limitaciones:

Vayamos a lo práctico, vamos a crear una clase vehículo y veremos cómo se serializa:


using System;
using System.Xml.Serialization;

namespace XMLSerializerDemo
{			
	public class Vehiculo
	{
		public string Marca;
		public string Modelo;
		public string Matricula;

		public Vehiculo()
		{
		}

		public Vehiculo(string marca, string modelo, string matricula):this()
		{
			this.Marca=marca;
			this.Modelo=modelo;
this.Matricula=matricula; } } class Class1 { [STAThread] static void Main(string[] args) { Console.WriteLine("Un Vehiculo:"); Vehiculo miCoche=new Vehiculo("Ford","Fiesta","ABC2051"); //Creamos un serializer para la clase Vehiculo XmlSerializer serializer=new XmlSerializer(typeof(Vehiculo)); //Mandamos el XML a la salida de consola serializer.Serialize(Console.Out,miCoche); } } }

No podía ser más fácil. Serializar un objeto es útil para poder recuperar la información más tarde, veamos un ejemplo:


  	Vehiculo miCoche=new Vehiculo("Ford","Fiesta");
	XmlSerializer serializer=new XmlSerializer(typeof(Vehiculo));

	//Guardamos el vehiculo a un fichero
	Console.WriteLine("Guardando vehículo: {0} {1} {2}",
			miCoche.Marca, miCoche.Modelo, miCoche.Matricula);
	System.IO.StreamWriter w=new System.IO.StreamWriter("vehiculo.xml");
	serializer.Serialize(w,miCoche);
	w.Close();

	//Recuperamos el vehiculo del fichero
	try
	{
		System.IO.StreamReader r=new System.IO.StreamReader("vehiculo.xml");			
		Vehiculo copia= (Vehiculo) serializer.Deserialize(r);
		r.Close();
		Console.WriteLine("La copia recuperada es: {0} {1}{2}",
				miCoche.Marca, miCoche.Modelo, miCoche.Matricula);
  	}
	catch(Exception ex)
	{
		//por si hay un error al leer el fichero
		Console.WriteLine(ex.ToString());
	}

Como vemos, el método Deserialize crea automáticamente una instancia de la clase y la rellena con los datos presentes en el fichero Xml. Esto explica porqué es necesario un constructor por defecto de la clase, ya que de otra manera el XmlSerializer no sabría a que constructor llamar.

 

Control de la serialización mediante atributos

Podemos indicar al XmlSerializer cómo deben serializarse las variables y propiedades de una clase indicándolo mediante atributos.

Es posible decidir como debe codificarse una propiedad, si tiene que ser un elemento (así es por defecto) o un atributo en el Xml, podemos cambiar el nombre o el tipo de datos:


  	[XmlAttribute]
	public string Marca;
	[XmlAttribute]
	public string Modelo;
[XmlElement("Fecha")]
public DateTime FechaDeCompra;

Por ejemplo, el tipo de datos xs:date no tiene una representación directa en .Net, lo más parecido es un DateTime. Para asegurarnos que sólo se serializa la parte de fecha debemos definir la variable del siguiente modo:


	[XmlElement(DataType="date")]
	public DateTime FechaDeCompra;
  

Serializar colecciones no tipificadas es posible usando el XmlArrayAttribute y el XmlArrayItemAttribute para indicar que tipo de datos representa esa colección:


	public class Aparcamiento
	{
		[XmlArrayItem("Vehiculo",typeof(Vehiculo)), XmlArray("Vehiculos")]
		public System.Collections.ArrayList Vehiculos;

		public Aparcamiento()
		{
			Vehiculos=new System.Collections.ArrayList();
		}
	}

	class Class1
	{
		static void Main(string[] args)
		{
			Vehiculo miCoche=new Vehiculo("Ford","Fiesta","ABC2051");
			miCoche.FechaDeCompra=DateTime.Today;

			Aparcamiento aparcamiento=new Aparcamiento();
			aparcamiento.Vehiculos.Add(miCoche);

			XmlSerializer serializer = new XmlSerializer(typeof(Aparcamiento));

			serializer.Serialize(Console.Out,aparcamiento);

		}
	}

Si tenemos propiedades que no deseamos que sean serializadas podemos indicarlo con el atributo XmlIgnore


	[XmlIgnore]
	public string ClaveSecreta;
  

Creación de clases desde una definición XML

El framework SDK incluye una herramienta llamada xsd.exe que sirve principalmente para crear clases C# o VB.Net desde un fichero xsd y viceversa.

Podemos comprobar el esquema xsd que definen las clases anteriores llamando al xsd.exe:


	xsd.exe XMLSerializerDemo.exe

El comando nos creará un fichero llamado "schema0.xsd". Para crear las clases a partir del esquema:


	xsd.exe /classes schema0.xsd

Las clase creadas por el esquema no tienen porqué ser exactas a las originales. El xsd no contiene datos sobre la implementación sino sólo sobre la organización de la información.

Conclusiones y notas

El XmlSerializer es una clase que está orientada a datos y resulta fácil de usar cuando queremos guardar los datos públicos de objetos .Net a disco y datos xml en clases .Net.

Hay clases que no podemos serializar porque la información que manejan es privada, las propiedades que muestran son sólo de lectura, o son árboles de objetos complejos. Para éste tipo de clases habrá que usar otros serializadores más avanzados como el SoapFormatter o el BinaryFormater que están pensadas para transferir objetos de un escenario a otro.


ir al índice