Programação, diversão e arte. Por Ricardo Giaviti
Posts tagged xhtml
Lendo XML com o REXML – Ruby
Jul 10th
Ruby tem hoje uma das bibliotecas mais impressionantes e fáceis para se manipular informações em formato XML. A biblioteca REXML (Ruby Electric XML).
Essa biblioteca é baseada na biblioteca Electric XML para Java, porém em Ruby é bem mais fácil de se usar tal biblioteca. Aliás, você não fica restrito apenas a manipulação de XML com o REXML, você também poderá usá-la para manipulação de informações no formato XHTML. Como o XHTML tem padrões rigorosos definidos, podemos usar o REXML tranqüilamente. Mas se você precisa manipular HTML, use o hpricot.
Nesse post, eu mostro o básico de uma leitura XML usando a REXML. Em nosso exemplo utilizaremos o webservice de pesquisa do Yahoo. Basicamente iremos ler o XML que o Yahoo nos fornece e iremos exibi-los em console.
Primeiro de tudo vamos ver qual a estrutura do XML que o Yahoo nos fornece para fazermos a leitura. A URL do XML é essa: http://api.search.yahoo.com/WebSearchService/V1/webSearch?appid=YahooDemo&query=metallica&results=5
Repare na URL que eu passei acima as variáveis que passei via GET. Uma é a palavra chave de busca (query) e a outra o número de resultados que eu quero por página (results). Estão com os valores “metallica” e “5” respectivamente. Se quiser se aprofundar na API de busca do Yahoo, consulte o site do developers do Yahoo.
Voltando a XML fornecida pelo Yahoo, vamos analisa-la:
Cada “caixa” em azul representa um nó no XML. Tudo começa com um nó raiz (ResultSet) e depois desce para o nó de resultado (Result). Esse nós repsenta um item do resultado da pesquisa feita no Yahoo. Se houve mais resultados, então o nó Result é repetido.
Em nosso tutorial, vamos ler as informações que estão nos nós “Title”, “Summary”, “Url” e “MimeType” que não se encontra no mapeamento acima porque não houve espaço para colocar todos os nós. De uma olhada no documento do Yahoo que você irá ver lá.
Agora que sabemos as informações que iremos ler, vamos começar a codificar.
Vamos criar uma classe “Buscador” que irá se conectar ao webservice do Yahoo, ler toda a XML e inicializar nossos atributos de instância no construtor. Depois criaremos um método que irá ler os nós específicos do XML que queremos.
Comecemos pelos imports das bibliotecas e pelo construtor:
# Leitura de XML usando a biblioteca REXML # do Ruby. Em nosso exemplo usaremos o # webservice de busca do Yahoo. class Buscador # Import dos GEMs usados e do REXML require 'rubygems' require 'open-uri' require 'rexml/document' #Vamos inicializar as variáveis para a busca e instanciar #nosso objeto REXML que será usado para a busca no Yahoo. def initialize(keywords, resultado_pagina) @keywords = keywords @resultado_pagina = resultado_pagina @url_yahoo = "http://api.search.yahoo.com/WebSearchService/V1/ webSearch?appid=YahooDemo&query=#{@keywords}&results=#{@resultado_pagina}" # Aqui você pode usar o open do gem open-uri ou # a classe net/http. O open é bem mais simples :). xml_data = open(@url_yahoo) @obj_rexml = REXML::Document.new(xml_data.read) end end
Repare no código acima que nosso construtor recebe dois parâmetros. O keywords são as palavras chave que usaremos na busca e o resultado_pagina é o número de resultados que queremos que sejam exibidos no XML. Esse parâmetros são aqueles já explicados acima nesse mesmo post.
Outro detalhe no código é o uso do open. Nele, passamos somente a URL que queremos ler e ele nos retorna os dados com o método read. Incrível. Cada vez mais eu gosto de Ruby!
Logo abaixo do open, está a instanciação do objeto REXML, o qual usaremos para ler o XML no método que criaremos.
Criado o construtor, vamos criar nosso pequeno método que faz a leitura do XML e nos retorna o resultado.
A cada resultado que o Yahoo nos retornar, iremos criar um hash para esse resultado. Preenchido o hash com as informações do XML colocaremos esse hash dentro de um array. Faremos isso até finalizar a leitura do XML. Terminada a leitura, retornaremos o array. Nossos resultados estarão bem estruturados dentro do array.
Vamos ao método da busca:
# Esse método realiza a leitura do xml e retorna um array de hash # com o resultado da leitura. def buscar lista_resultado = Array.new #array com todos os resultados # Caminho dos nos no XML. Dependendo do que você quiser # no XML, vai ser aqui você irá muda. nos = "ResultSet/Result" # Loop entre os nos do XML definido acima @obj_rexml.elements.each(nos) do |elemento| resultado = Hash.new #hash que vai conter um resultado resultado[:titulo] = elemento.text("Title") resultado[:descricao] = elemento.text("Summary") resultado[:link] = elemento.text("Url") resultado[:tipo] = elemento.text("MimeType") # Guarda o hash no array e continua o loop lista_resultado < < resultado end # Retorna o Array com os resultados return lista_resultado end
Explicando o que se passa nesse método:
- lista_resultado: Nosso array onde ficarão os hash de cada resultado individual.
- nos: é o “caminho” no XML que queremos. Tudo o que estiver dentro desse caminho, ele irá nos retornar.
- @obj_rexml.elements.each(nos) do |elemento|: Loop entre os nós dentro do caminho passado.
- resultado: Hash que representa um resultado individual.
- resultado[:titulo] = elemento.text(“Title”): Inserção no Hash (posição :title) o elemento XML que contém um nó chamado “Title”.
- lista_resultado << resultado: Insere o hash no array
- return lista_resultado: Retorna o array com os resultados!
O método .text(nó) chamado pelo objeto elemento significa que queremos o texto que está dentro do nó passado como parâmetro. Quando há um atributo no nó, podemos utilizar o método .attributte(atributo). Por exemplo, supondo que um nó possua um atributo “id=5” da seguinte forma: <title id=”5”>Texto do Título</title>. Então poderíamos utilizar o método assim:
elemento.attributte(“id”)
=> 5
Bem legal!
Pronto! Muito simples. Nossa classe está pronta. No final das contas teremos o seguinte código:
class Buscador require 'rubygems' require 'open-uri' require 'rexml/document' def initialize(keywords, resultado_pagina) @keywords = keywords @resultado_pagina = resultado_pagina @url_yahoo = "http://api.search.yahoo.com/WebSearchService/V1/ webSearch?appid=YahooDemo&query=#{@keywords}&results=#{@resultado_pagina}" xml_data = open(@url_yahoo) @obj_rexml = REXML::Document.new(xml_data.read) end def buscar lista_resultado = Array.new #array com todos os resultados nos = "ResultSet/Result" @obj_rexml.elements.each(nos) do |elemento| resultado = Hash.new #hash que vai conter um resultado resultado[:titulo] = elemento.text("Title") resultado[:descricao] = elemento.text("Summary") resultado[:link] = elemento.text("Url") resultado[:tipo] = elemento.text("MimeType") lista_resultado < < resultado end return lista_resultado end end
Para testarmos a classe recém-criada, você pode implementar o seguinte script logo após o fechamento da classe:
# Configurações do script # As configurações abaixo são configurações básicas para uso no # webservie do Yahoo. keywords = "metallica+one" resultados_por_pagina = 10 busca = Buscador.new(keywords, resultados_por_pagina) resultados = busca.buscar resultados.each do |item_achado| puts "Titulo: #{item_achado[:titulo]}" puts "Descricao: #{item_achado[:descricao]}" puts "Link: #{item_achado[:link]}" puts "Tipo: #{item_achado[:tipo]}" puts "-------------------------------------" end
Executando o nosso exemplo teremos os seguintes exemplos de resultados:
Titulo: One (Metallica song) - Wikipedia, the free encyclopedia
Descricao: Metallica won their first Grammy Award in 1990 for "One", winning Best Metal ... "One" was written in November 1987 by Metallica's principal composers — rhythm ...
Link: http://en.wikipedia.org/wiki/One_(Metallica_song)
Tipo: text/html
-------------------------------------
Titulo: YouTube - Metallica - One
Descricao: Video of One by MetallicAMovie: Johnny Got His Gun ... one of the best songs by MetallicA. kingxwrong (2 hours ago) Show Hide +1. Marked as spam ...
Link: http://www.youtube.com/watch?v=-j39ABZyzek
Tipo: text/html
-------------------------------------
Titulo: YouTube - Metallica- One
Descricao: Metallica's music video "One" ... One - Metallica (Live 1989) 07:00 From: metallicafx. Views: 2,551,898. Loading...
Link: http://www.youtube.com/watch?v=JwW9L_qzqp8
Tipo: text/html
Com esse simples (bem simples mesmo) exemplo que criamos, mostramos a força do REXML. Usando o próprio Yahoo, podemos criar nosso próprio search engine com o Rails baseado no motor de busca do Yahoo. Por que não? Afinal as possibilidade são infinitas.
Se quiser se aprender mais sobre a manipulação de REXML segue alguns links:
- API do REXML: http://www.ruby-doc.org/stdlib/libdoc/rexml/rdoc/index.html
- Sobre o Electric XML: http://www.xml.com/pub/r/1098
- Yahoo Developer Network: http://developer.yahoo.com/
- Tutorial um pouco mais complexo: http://www.xml.com/pub/a/2005/11/09/rexml-processing-xml-in-ruby.html
É isso pessoal. Espero que tenham gostado do REXML assim como eu e até o próximo post!






Recent Comments