Serializar e Deserializar objetos em C# é bem simples. Vamos usar para isso o XmlSerializer e seus métodos: Serialize e Deserialize.
Vamos ver também como usar o XmlWriterSettings. Ver como salvar o XML, fazer download ou simplesmente retornar o XML gerado.
Para os primeiros exemplos vamos usar a classe abaixo.
public class Usuario
{
public string Nome { get; set; }
public int Idade { get; set; }
}
Salvar um List<T> em XML.
using System.IO;
using System.Xml.Serialization;
...
protected void Page_Load(object sender, EventArgs e)
{
//Lista de usuários
List<Usuario> usuarios = new List<Usuario>();
//Criando a lista de usuários
for (int i = 1; i <= Convert.ToInt32(3); i++)
{
Usuario usuario = new Usuario();
usuario.Nome = "Nome " + i;
usuario.Idade = i;
usuarios.Add(usuario);
}
//Criar o arquivo XML - usuarios.xml - na raiz da aplicação
using (TextWriter textWriter = new StreamWriter(Server.MapPath("~/usuarios.xml")))
{
//Definir o Type e o elemento raiz do XML (usuarios)
XmlSerializer ser = new XmlSerializer(usuarios.GetType(), new XmlRootAttribute("usuarios"));
//Serializar o list para o TextWriter e salvar os dados no XML
ser.Serialize(textWriter, usuarios);
}
}
Resultado:
<?xml version="1.0" encoding="utf-8"?>
<usuarios xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Usuario>
<Nome>Nome 1</Nome>
<Idade>1</Idade>
</Usuario>
<Usuario>
<Nome>Nome 2</Nome>
<Idade>2</Idade>
</Usuario>
<Usuario>
<Nome>Nome 3</Nome>
<Idade>3</Idade>
</Usuario>
</usuarios>
Deserializar o XML para List<T>
using System.IO;
using System.Xml.Serialization;
...
protected void Page_Load(object sender, EventArgs e)
{
//Lista de usuários
List<Usuario> usuarios = new List<Usuario>();
//Definir o Type no XmlSerializer (List<Usuario>)
XmlSerializer ser = new XmlSerializer(usuarios.GetType(), new XmlRootAttribute("usuarios"));
//Usar o FileStream para abrir e ler o arquivo XML
FileStream fs = new FileStream(Server.MapPath("~/usuarios.xml"), FileMode.Open);
//Deserializar o XML para o tipo List<Usuario>
usuarios = (List<Usuario>)ser.Deserialize(fs);
//Usar o foreach para retornar o Nome e a Idade dos Usuários do XML Deserializados para List<Usuario>
foreach (Usuario usuario in usuarios)
{
Response.Write(string.Format("{0} - {1} <br />", usuario.Nome, usuario.Idade));
}
}
Resultado:
Nome 1 - 1
Nome 2 - 2
Nome 3 - 3
Gostou do exemplo de Serializar e Deserializar uma Lista Genérica?
Agora vamos ver como fazer download e como responder o XML gerado na tela. Veja o exemplo:
using System.IO;
using System.Xml.Serialization;
...
protected void Page_Load(object sender, EventArgs e)
{
//Lista de usuários
List<Usuario> usuarios = new List<Usuario>();
//Criando a lista de usuários
for (int i = 1; i <= Convert.ToInt32(3); i++)
{
Usuario usuario = new Usuario();
usuario.Nome = "Nome " + i;
usuario.Idade = i;
usuarios.Add(usuario);
}
//Definir o Type e o elemento raiz do XML (usuarios)
XmlSerializer ser = new XmlSerializer(usuarios.GetType(), new XmlRootAttribute("usuarios"));
//Instanciar o StringWriter
StringWriter writer = new StringWriter();
//Serializar o List para o StringWriter
ser.Serialize(writer, usuarios);
//Limpar o conteúdo
Response.Clear();
//Respnder o XML na tela
Response.Write(writer.ToString());
//Definir que o conteúdo é do tipo XML
Response.ContentType = "text/xml";
//Para fazer o download basta descomentar a linha abaixo
//Response.AddHeader("Content-Disposition", "attachment;filename=usuarios.xml");
//Parar por aqui
Response.End();
}
Para responder o XML na tela usamos o StringWriter e para fazer o download do XML basta adicionar a linha abaixo.
Response.AddHeader("Content-Disposition", "attachment;filename=usuarios.xml");
Até agora vimos exemplos de conversão automática de Class para XML, tudo muito simples e tranquilo. Agora vamos para os exemplos mais complexos, onde vamos usar o XmlElement, XmlAttribute na declaração de propriedades das classes.
Nossa classe de exemplo ficará assim:
public class Contato
{
[XmlAttribute("ativo")]
public bool Ativo;
[XmlElement("nome")]
public string NomeCompleto { get; set; }
[XmlElement("email")]
public string EmailParticular { get; set; }
}
Quando usamos o XmlAttribute, podemos definir a propriedade da classe como um atributo de um elemento no XML. E usar o XmlElement pode servir para dar um nome diferente para o elemento XML, por exemplo.
using System.IO;
using System.Xml.Serialization;
...
protected void Page_Load(object sender, EventArgs e)
{
//Lista de usuários
List<Contato> contatos = new List<Contato>();
//Populando a lista de usuários
for (int i = 1; i <= Convert.ToInt32(3); i++)
{
Contato contato = new Contato();
contato.NomeCompleto = "Nome " + i;
contato.Ativo = true;
contato.EmailParticular = "email" + i + "@cbsa.com.br";
contatos.Add(contato);
}
//Criar o arquivo XML
using (TextWriter textWriter = new StreamWriter(Server.MapPath("~/contatos.xml")))
{
//Definir o Type e o elemento raiz do XML (contatos)
XmlSerializer ser = new XmlSerializer(contatos.GetType(), new XmlRootAttribute("contatos"));
//Serializar o list para o TextWriter e salvar os dados no XML
ser.Serialize(textWriter, contatos);
}
}
Resultado:
<?xml version="1.0" encoding="utf-8"?>
<contatos xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Contato ativo="true">
<nome>Nome 1</nome>
<email>[email protected]</email>
</Contato>
<Contato ativo="true">
<nome>Nome 2</nome>
<email>[email protected]</email>
</Contato>
<Contato ativo="true">
<nome>Nome 3</nome>
<email>[email protected]</email>
</Contato>
</contatos>
O problema de Serializar um objeto é que ele cria por padrão a declaração do XML e os namespace XSI e XSD, que na maioria das vezes não são necessários.
Então para remover a declaração do XML (<?xml version="1.0" encoding="utf-8"?>) usamos o XmlWriterSettings, veja abaixo:
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
XmlWriter writer = XmlTextWriter.Create(stream, settings);
E para remover os namespaces XSI e XSD do XML, vamos utilizar o XmlSerializerNamespaces, veja abaixo:
XmlSerializerNamespaces xmlNamespace = new XmlSerializerNamespaces();
//Adicionar um item vazio para remover o Namespace xsi, xsd do XML
xmlNamespace.Add("", "");
...
ser.Serialize(writer, list, xmlNamespace);
Abaixo o código completo que mostra como omitir a declaração do XML e omitir os Namespaces.
Também vai mostrar como identar o XML e definir a codificação do arquivo, neste caso UTF8.
Aproveitando o embalo, vamos ver como criar um novo namespace também.
using System.IO;
using System.Xml.Serialization;
using System.Text;
using System.Xml;
...
protected void Page_Load(object sender, EventArgs e)
{
//Lista de usuários
List<Contato> contatos = new List<Contato>();
//Populando a lista de usuários
for (int i = 1; i <= Convert.ToInt32(3); i++)
{
Contato contato = new Contato();
contato.NomeCompleto = "Nome " + i;
contato.Ativo = true;
contato.EmailParticular = "email" + i + "@cbsa.com.br";
contatos.Add(contato);
}
//Criar um Namespace para o XML
XmlSerializerNamespaces xmlNamespace = new XmlSerializerNamespaces();
//Adicionar um item vazio para remover o Namespace xsi, xsd do XML
xmlNamespace.Add("", "");
//Obviamente o XmlSerializerNamespaces serve para adicionar um novo namespace também.
//A linha abaixo vai adicionar xsd no XML
xmlNamespace.Add("namespace", "value");
//Configurações do XML
XmlWriterSettings settings = new XmlWriterSettings();
//A linha abaixo omite a declaração do XML: <?xml version="1.0" encoding="utf-8"?>
settings.OmitXmlDeclaration = true;
//Definir a codificação do XML
settings.Encoding = Encoding.UTF8;
//Identar o XML automaticamente
settings.Indent = true;
//Criar o arquivo XML
using (TextWriter textWriter = new StreamWriter(Server.MapPath("~/contatos.xml")))
{
//Usar o Create do XmlTextWriter para aplicar as configurações no XML
XmlWriter writer = XmlTextWriter.Create(textWriter, settings);
//Definir o Type e o elemento raiz do XML (contatos)
XmlSerializer ser = new XmlSerializer(contatos.GetType(), new XmlRootAttribute("contatos"));
//Serializar o list, com o Namespace para o XmlWriter e salva os dados no XML
ser.Serialize(writer, contatos, xmlNamespace);
}
}
Resultado:
<contatos xmlns:namespace="value">
<Contato ativo="true">
<nome>Nome 1</nome>
<email>[email protected]</email>
</Contato>
<Contato ativo="true">
<nome>Nome 2</nome>
<email>[email protected]</email>
</Contato>
<Contato ativo="true">
<nome>Nome 3</nome>
<email>[email protected]</email>
</Contato>
</contatos>
Se precisar converter o XmlWriter para string, você pode usar o código abaixo. Assim não será preciso salvar o XML, apenas fazer um Response.Write.
using System.IO;
using System.Xml.Serialization;
using System.Text;
using System.Xml;
...
protected void Page_Load(object sender, EventArgs e)
{
//Lista de usuários
List<Contato> contatos = new List<Contato>();
//Populando a lista de usuários
for (int i = 1; i <= Convert.ToInt32(3); i++)
{
Contato contato = new Contato();
contato.NomeCompleto = "Nome " + i;
contato.Ativo = true;
contato.EmailParticular = "email" + i + "@cbsa.com.br";
contatos.Add(contato);
}
//Criar um Namespace para o XML
XmlSerializerNamespaces xmlNamespace = new XmlSerializerNamespaces();
//Adicionar um item vazio para remover o Namespace xsi, xsd do XML
xmlNamespace.Add("", "");
//Obviamente o XmlSerializerNamespaces serve para adicionar um novo namespace também.
//A linha abaixo vai adicionar xsd no XML
xmlNamespace.Add("namespace", "value");
//Configurações do XML
XmlWriterSettings settings = new XmlWriterSettings();
//A linha abaixo omite a declaração do XML: <?xml version="1.0" encoding="utf-8"?>
settings.OmitXmlDeclaration = true;
//Definir a codificação do XML
settings.Encoding = Encoding.UTF8;
//Identar o XML automaticamente
settings.Indent = true;
//MemoryStream para colocar o XML em memória
MemoryStream stream = new MemoryStream();
//Usar o Create do XmlTextWriter para aplicar as configurações no XML
XmlWriter writer = XmlTextWriter.Create(stream, settings);
//Definir o Type e o elemento raiz do XML (contatos)
XmlSerializer ser = new XmlSerializer(contatos.GetType(), new XmlRootAttribute("contatos"));
//Serializar o list, com o Namespace para o XmlWriter
ser.Serialize(writer, contatos, xmlNamespace);
//Converter o XmlWriter para string
var buffer = new byte[stream.Length];
stream.Read(buffer, 0, (int)stream.Length);
string resultado = Encoding.UTF8.GetString(stream.ToArray());
//Retornar o resultado
Response.Write(resultado);
Response.End();
}