XStream: Criando e lendo arquivos XML
Autor: andii.brunetta | Publicado: 2011-06-10T14:14:00-04:00


Caso ainda não tenha precisado criar ou ler arquivos XML em Java, pelo menos já parou pra pensar como fazer isso? Criar uma String gigante concatenando valores e tags? Hoje em dia não há necessidade de se utilizar métodos tão "complexos" assim. Existe uma biblioteca chamada de XStream, onde objetos podem ser transformados em XML, e vice versa.
Obs: o XStream gera uma String em formato de XML, e não o arquivo XML propriamente dito, mas este é gerado com a ajuda do FileOutputStream do Java.
Então para fazer este exemplo vamos precisar de dois .jar, um é do próprio XStream e o outro é o Dom4J. Para baixar os dois juntos,&nbsp;clique aqui.

Estrutura do projeto
Nosso projeto irá ficar com essa estrutura:




Depois de muito tempo venho editar esta postagem sobre XStream...
Dentro do pacote model temos duas classes, um é o Endereco e a outra é Pessoa.
Classe Endereco:
@XStreamAlias("endereco")
public class Endereco {

    private String rua;
    private String cidade;

    //gettters e setters
}

A anotação @XStreamAlias é necessária quando vai fazer a leitura de uma String XML.
A Classe Pessoa:
public class Pessoa {

    private String nome;
    private String cpf;
    private List&lt;Endereco&gt; enderecos;
  
    //getters e setters
}


Bom agora vamos ver o que desejamos fazer e como fazer... Vamos começar pelo mais simples, caso queira gerar um XML de um endereço que está dessa forma:
&lt;endereco&gt;
  &lt;rua&gt;Rua das araras&lt;/rua&gt;
  &lt;cidade&gt;Primavera do Leste&lt;/cidade&gt;
&lt;/endereco&gt;


Eu preciso do seguinte código:
private static void gravaEndereco() {
        Endereco endereco = new Endereco();
        endereco.setCidade("Primavera do Leste");
        endereco.setRua("Rua das araras");

        XStream xStream = new XStream();
        xStream.alias("endereco", Endereco.class);
       
        File arquivo = new File("endereco.xml");
        FileOutputStream gravar;
        try {
            gravar = new FileOutputStream(arquivo);
            gravar.write(xStream.toXML(endereco).getBytes());
            gravar.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }


Lembrando que a parte de gravar o arquivo não é do XStream, a String é gerada pelo seguinte código: xStream.toXML(endereco), o mesmo vale para os próximos métodos...

Agora caso queira gravar uma lista de endereços em XML, que fique dessa forma:
&lt;enderecos&gt;
  &lt;endereco&gt;
    &lt;rua&gt;Rua abc&lt;/rua&gt;
    &lt;cidade&gt;Cuiaba&lt;/cidade&gt;
  &lt;/endereco&gt;
  &lt;endereco&gt;
    &lt;rua&gt;Avenida São João&lt;/rua&gt;
    &lt;cidade&gt;Primavera do Leste&lt;/cidade&gt;
  &lt;/endereco&gt;
&lt;/enderecos&gt;


É necessário o seguinte método:
private static void gravaListaEndereco() {
        List&lt;Endereco&gt; enderecos = new ArrayList&lt;Endereco&gt;();

        Endereco e1 = new Endereco();
        e1.setCidade("Cuiaba");
        e1.setRua("Rua abc");
        enderecos.add(e1);

        Endereco e2 = new Endereco();
        e2.setCidade("Primavera do Leste");
        e2.setRua("Avenida São João");
        enderecos.add(e2);

        XStream xStream = new XStream();
        xStream.alias("enderecos", List.class);
        xStream.alias("endereco", Endereco.class);

        File arquivo = new File("enderecos.xml");
        FileOutputStream gravar;
        try {
            gravar = new FileOutputStream(arquivo);
            gravar.write(xStream.toXML(enderecos).getBytes());
            gravar.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }


Agora vamos ver algo mais complicado, que é gravar objetos que contenham listas dentro dele... ou seja vamos criar um XML que represente uma lista de pessoas (nosso model lá do início):
&lt;pessoas&gt;
  &lt;pessoa&gt;
    &lt;nome&gt;Andii&lt;/nome&gt;
    &lt;cpf&gt;123.123.123-34&lt;/cpf&gt;
    &lt;enderecos&gt;
      &lt;endereco&gt;
        &lt;rua&gt;Rua 123&lt;/rua&gt;
        &lt;cidade&gt;Primavera do Leste&lt;/cidade&gt;
      &lt;/endereco&gt;
    &lt;/enderecos&gt;
  &lt;/pessoa&gt;
  &lt;pessoa&gt;
    &lt;nome&gt;Maria&lt;/nome&gt;
    &lt;cpf&gt;345.656.235-98&lt;/cpf&gt;
    &lt;enderecos&gt;
      &lt;endereco&gt;
        &lt;rua&gt;Avenida das flores&lt;/rua&gt;
        &lt;cidade&gt;Cuiabá&lt;/cidade&gt;
      &lt;/endereco&gt;
      &lt;endereco&gt;
        &lt;rua&gt;Rua das abelhas&lt;/rua&gt;
        &lt;cidade&gt;Cuiabá&lt;/cidade&gt;
      &lt;/endereco&gt;
    &lt;/enderecos&gt;
  &lt;/pessoa&gt;
&lt;/pessoas&gt;

Para gerar esta estrutura precisamos o seguinte método:
private static void gravaListaCompleta() {
        Pessoa pessoa1 = new Pessoa();
        pessoa1.setNome("Andii");
        pessoa1.setCpf("123.123.123-34");

        Endereco endereco1 = new Endereco();
        endereco1.setCidade("Primavera do Leste");
        endereco1.setRua("Rua 123");

        List&lt;Endereco&gt; enderecos1 = new ArrayList&lt;Endereco&gt;();
        enderecos1.add(endereco1);
        pessoa1.setEnderecos(enderecos1);

        Pessoa pessoa2 = new Pessoa();
        pessoa2.setNome("Maria");
        pessoa2.setCpf("345.656.235-98");

        Endereco endereco2 = new Endereco();
        endereco2.setCidade("Cuiabá");
        endereco2.setRua("Avenida das flores");

        Endereco endereco3 = new Endereco();
        endereco3.setCidade("Cuiabá");
        endereco3.setRua("Rua das abelhas");

        List&lt;Endereco&gt; enderecos2 = new ArrayList&lt;Endereco&gt;();
        enderecos2.add(endereco2);
        enderecos2.add(endereco3);
        pessoa2.setEnderecos(enderecos2);

        List&lt;Pessoa&gt; pessoas = new ArrayList&lt;Pessoa&gt;();
        pessoas.add(pessoa1);
        pessoas.add(pessoa2);

        XStream xStream = new XStream();

        xStream.alias("pessoas", List.class);
        xStream.alias("pessoa", Pessoa.class);
        xStream.alias("endereco", Endereco.class);

        File arquivo = new File("pessoas.xml");
        FileOutputStream gravar;
        try {
            gravar = new FileOutputStream(arquivo);
            gravar.write(xStream.toXML(pessoas).getBytes());
            gravar.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

E enfim para lermos uma String XML, precisamos do método abaixo, para o exemplo de leitura eu estarei utilizando o arquivo gerado em um dos métodos acima, aquele que gera uma lista de endereços:
private static void lerXML() {
        try {
            XStream xStream = new XStream(new Dom4JDriver());
            xStream.alias("enderecos", ArrayList.class);
            xStream.processAnnotations(Endereco.class);

            BufferedReader input = new BufferedReader(new FileReader("enderecos.xml"));
            ArrayList&lt;Endereco&gt; enderecos = (ArrayList) xStream.fromXML(input);
            input.close();

            for (Endereco endereco : enderecos) {
                System.out.println("Endereço: " + endereco.getRua() + " - " + endereco.getCidade());
            }

        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

Veja que eu leio o arquivo utilizando BufferedReader e tendo esse arquivo "carregado" utilizo do XStream para gerar uma lista para mim... Lembrando que dessa vez eu preciso da anotação lá na classe Endereco, o resultado da leitura do método acima é:
Endereço: Rua abc - Cuiaba
Endereço: Avenida São João - Primavera do Leste

Bom... peço desculpas pela demora a fazer as explicações do XStream... Mas está aí :)

Observação final: como vocês podem ver, eu não coloquei um endereço fixo de onde armazenar meus arquivos, era apenas new file("endereco.xml") ... para quem não sabe isso gera o arquivo dentro da pasta do projeto.