Skip to main content

Serialización XML

Extensible Markup Language (XML) es un lenguaje de marcado similar a HTML especificado por el World Wide Web Consortium (W3C).

W3C es un consorcio internacional que genera recomendaciones y estándares que aseguran el crecimiento de la World Wide Web (www) a largo plazo.

La serialización XML transforma los atributos y propiedades de lectura-escritura públicas de un objeto en memoria en una secuencia de datos que puede ser procesada por cualquier aplicación independientemente de la plataforma en la que fue construida o sobre la que se ejecute.

Sintaxis de XML

Como todo lenguaje, XML tiene reglas de sintaxis que permiten su posterior interpretación. Se compone de etiquetas de apertura y cierre, por ejemplo:

<OrderForm>
<OrderDate>12/12/01</OrderDate>
</OrderForm>

En el ejemplo anterior tenemos la etiqueta <OrderForm></OrderForm> que representa a un objeto de la clase OrderForm y tiene anidada la propiedad OrderDate representada por la etiqueta <OrderDate></OrderDate> que contiene el valor de dicha propiedad, 12/12/01.

Correspondería a la serialización de un objeto de la siguiente clase:

public class OrderForm
{
public DateTime OrderDate;
}

Otro ejemplo:

Alumno nuevoAlumno = new Alumno("Juan Perez", 
new DateTime(2000, 12, 12), 7.8f);
nuevoAlumno.Materias.Add("Programación II");
nuevoAlumno.Materias.Add("Laboratorio de computación II");

Alumno nuevoAlumno2 = new Alumno("Leo Lopez",
new DateTime(2000, 12, 12), 7.8f);
nuevoAlumno2.Materias.Add("Arquitectura y sistemas operativos");
nuevoAlumno2.Materias.Add("Inglés II");
nuevoAlumno2.Materias.Add("Metodología de la investigación");

List<Alumno> nuevosAlumnos = new List<Alumno>()
{
nuevoAlumno,
nuevoAlumno2
};

Serializar nuevosAlumnos resultaría en el siguiente XML:

<?xml version="1.0" encoding="utf-8"?>
<!-- Array de objetos Alumno -->
<ArrayOfAlumno
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
>
<Alumno> <!-- Objeto Alumno -->
<NombreCompleto>Juan Perez</NombreCompleto> <!-- Propiedad texto -->
<FechaNacimiento>2000-12-12T00:00:00</FechaNacimiento> <!-- Propiedad fecha -->
<Promedio>7.8</Promedio> <!-- Propiedad numérica -->
<Materias> <!-- Array anidado -->
<string>Programación II</string>
<string>Laboratorio de computación II</string>
</Materias>
</Alumno> <!-- Fin objeto -->
<Alumno> <!-- Otro Objeto Alumno -->
<NombreCompleto>Leo Lopez</NombreCompleto>
<FechaNacimiento>2000-12-12T00:00:00</FechaNacimiento>
<Promedio>7.8</Promedio>
<Materias>
<string>Arquitectura y sistemas operativos</string>
<string>Inglés II</string>
<string>Metodología de la investigación</string>
</Materias>
</Alumno> <!-- Fin objeto -->
</ArrayOfAlumno> <!-- Fin array -->

Serializando a XML

Para serializar un objeto este debe contar con atributos o propiedades de lectura-escritura públicos y un constructor público sin parámetros.

Luego debemos utilizar un objeto de tipo XmlSerializer del espacio de nombres System.Xml.Serialization y llamar a su método Serialize. Una de sus sobrecargas recibe el objeto a serializar y una instancia de StreamWriter que se utiliza para guardar el objeto serializado en un archivo.

Vemos un ejemplo:

public class Alumno
{
private string nombreCompleto;
private DateTime fechaNacimiento;
private List<Materia> materias;
private float promedio;

public string NombreCompleto
{
get
{
return nombreCompleto;
}
set
{
nombreCompleto = value;
}
}

public DateTime FechaNacimiento
{
get
{
return fechaNacimiento;
}
set
{
fechaNacimiento = value;
}
}

public float Promedio
{
get
{
return promedio;
}
set
{
promedio = value;
}
}

public Alumno()
{
materias = new List<Materia>();
}

public Alumno(string nombreCompleto, DateTime fechaNacimiento, float promedio) :this()
{
this.nombreCompleto = nombreCompleto;
this.fechaNacimiento = fechaNacimiento;
this.promedio = promedio;
}
}
static void Main(string[] args)
{
Alumno alumno = new Alumno("Juan Perez", new DateTime(2000, 12, 12), 7.8f);

using (StreamWriter streamWriter = new StreamWriter("alumno.xml"))
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Alumno));

xmlSerializer.Serialize(streamWriter, alumno);
}
}

En la carpeta bin/debug del proyecto encontraremos el archivo alumno.xml con el siguiente contenido:

<?xml version="1.0" encoding="utf-8"?>
<Alumno xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<NombreCompleto>Juan Perez</NombreCompleto>
<FechaNacimiento>2000-12-12T00:00:00</FechaNacimiento>
<Promedio>7.8</Promedio>
</Alumno>

Como vemos, el objeto de tipo Alumno se encuentra representado por la etiqueta <Alumno></Alumno> que contiene cada una de sus propiedades, también en forma de etiquetas, y los valores de las mismas.

Deserializando XML

Deserializar significa interpretar un texto que contiene objetos serializados y volver a convertirlos en objetos en memoria. Para deserializar desde formato XML se debe utilizar el método estático Deserialize de una instancia de XmlSerializer. Deserialize recibe una instancia de StreamReader que se utiliza para leer desde el archivo donde se encuentra el objeto serializado.

static void Main(string[] args)
{
using (StreamReader streamReader = new StreamReader("alumno.xml"))
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Alumno));

Alumno alumno = xmlSerializer.Deserialize(streamReader) as Alumno;

Console.WriteLine($"Nombre: {alumno.NombreCompleto}");
Console.WriteLine($"Fecha de nacimiento: {alumno.FechaNacimiento}");
Console.WriteLine($"Promedio: {alumno.Promedio}");
}
}

La salida del código anterior es:

Nombre: Juan Perez
Fecha de nacimiento: 12/12/2000 00:00:00
Promedio: 7,8

Se trata exactamente del proceso opuesto. Debemos castear el resultado del método Deserialize al tipo de objeto al que estamos deserializando.