Mostrando postagens com marcador XStream. Mostrar todas as postagens
Mostrando postagens com marcador XStream. Mostrar todas as postagens

10 de junho de 2011

XStream: Criando e lendo arquivos XML

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, 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<Endereco> 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:
<endereco>
  <rua>Rua das araras</rua>
  <cidade>Primavera do Leste</cidade>
</endereco>

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:
<enderecos>
  <endereco>
    <rua>Rua abc</rua>
    <cidade>Cuiaba</cidade>
  </endereco>
  <endereco>
    <rua>Avenida São João</rua>
    <cidade>Primavera do Leste</cidade>
  </endereco>
</enderecos>

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

        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):
<pessoas>
  <pessoa>
    <nome>Andii</nome>
    <cpf>123.123.123-34</cpf>
    <enderecos>
      <endereco>
        <rua>Rua 123</rua>
        <cidade>Primavera do Leste</cidade>
      </endereco>
    </enderecos>
  </pessoa>
  <pessoa>
    <nome>Maria</nome>
    <cpf>345.656.235-98</cpf>
    <enderecos>
      <endereco>
        <rua>Avenida das flores</rua>
        <cidade>Cuiabá</cidade>
      </endereco>
      <endereco>
        <rua>Rua das abelhas</rua>
        <cidade>Cuiabá</cidade>
      </endereco>
    </enderecos>
  </pessoa>
</pessoas>
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<Endereco> enderecos1 = new ArrayList<Endereco>();
        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<Endereco> enderecos2 = new ArrayList<Endereco>();
        enderecos2.add(endereco2);
        enderecos2.add(endereco3);
        pessoa2.setEnderecos(enderecos2);

        List<Pessoa> pessoas = new ArrayList<Pessoa>();
        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<Endereco> 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.