por Cesar Cassiano Schimanco

Serializar objetos para XML - C#

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();
}

 

Comentários

Carregando comentários

Postar um novo comentário



Processando...