Gerando XML com vários models no Rails

Na semana passada eu escrevi um post sobre como gerar um XML a partir de um modelo no Rails, com algumas opções que facilitam a nossa vida. Mas e quando precisamos gerar um XML que não é formado só com os dados de um único modelo? Será que o to_xml resolve?

A princípio, a resposta é não. Primeiro porque uma vez que você tem uma instância de algum model (por exemplo, User.find(:first)), você não consegue adicionar a ele propriedades que não estão definidas no próprio modelo (ou através de algum método dele). Segundo que se você montar um vetor com modelos diferentes (por exemplo, User e Article), o XML será gerado usando o termo records para designar esse conjunto de objetos e record para designar cada elemento.

Isso se torna um problema quando você precisa exportar os dados do seu banco para outro sistema usando XML, como é o caso da troca de informação sobre atendimentos médicos, cujo padrão foi definido pela ANS. Esse padrão foi definido como Troca de Informações em Saúde Suplementar (TISS), e estabelece, usando um namespace próprio, como os dados devem ser formatados para que possam ser enviadas informações de faturamento, por exemplo.

Ah, sim, mas voltando à pergunta: e daí? Como eu faço isso?

Uma das inúmeras alternativas que existem é usar o Builder::XmlMarkup.

Para instalá-lo, execute:

gem install builder

e para utilizá-lo é muito simples:

xm = Builder::XmlMarkup.new(:indent => 4)
xm.instruct!
xm.html {
  xm.head {
    xm.title("History")
  }
  xm.body {
    xm.comment! "HI"
    xm.h1("Header")
    xm.p("paragraph")
  }
}

Veja que eu especifiquei que a identação do XML tem que conter 4 espaços. O código acima vai gerar o XML abaixo (HTML não deixa de ser XML!):

<?xml version="1.0" encoding="UTF-8"?>
<html>
  <head>
    <title>History</title>
  </head>
  <body>
    <! -- HI -->
    <h1>Header</h1>
    <p>paragraph</p>
  </body>
</html>

Uma particularidade do XmlMarkup que pode causar confusão no começo é que praticamente qualquer método que você tentar utilizar vai virar um atributo do xml. Ou seja, se você tentar utilizar xm.to_s no código acima, esperando que ele mostre todo o XML pra você como uma string, você pode se surpreender vendo que agora o teu XML tem mais um atributo: <to_s/>. Se você quiser que o teu objeto XmlMarkup vire uma string em outra variável, utilize o parâmetro :target do construtor. Assim, a variável que for passada como target sempre conterá uma string que é o teu XML.

Outra forma de criar atributos aninhados no XML através do XmlMarkup é usar um bloco de código, assim:

var = ""
xm = Builder::XmlMarkup.new(:target => var)
xm.tag!("html") do
  xm.tag!("head") do
    xm.tag!("title", "Título da página")
  end
end

Que vai gerar o seguinte:

<html>
  <head>
    <title>Título da página</title>
  </head>
</html>

Ou seja, a mesma coisa do exemplo anterior, só que feito de forma diferente. Repare que desta vez eu especifiquei o target do XmlMarkup. Dessa forma. a variável var conterá uma string que é o meu XML (e dessa forma não seremos tentados a usar xm.to_s)

E pra finalizar, aquilo que eu sempre digo: para mais detalhes, consulte a documentação ;-) .


Poderia avaliar este artigo, por favor?

1 Estrela2 Estrelas3 Estrelas4 Estrelas5 Estrelas (Nenhum voto)
Loading ... Loading ...

Posts relacionados