最初に結論
XMLで結果を吐き出すREST APIをRubyで用いたいなら、かなり役立つんじゃないかと思います。
sax-machineって?
XMLを、例えば普通にNokogiriなんかでパースすると、
1 2 | api = Nokogiri::XML.parse(open(URI.encode "http://ws.audioscrobbler.com/2.0/?method=track.search&track=夏&api_key=#{API_KEY}&limit=5")) puts api.search("/lfm/results/trackmatches/track[1]/name").inner_text |
みたいなすごいことになるので、せめて
1 | puts api.tracks[0].name |
みたいには書けないか? そんな夢を簡単に叶えるのが sax-machine ライブラリです。
準備
gemを入れる。Nokogiriに依存するので、環境によってはまずlibxml2-dev(el)とlibxslt-dev(el)も入れないといけません。
1 2 | sudo aptitude install libxml2-dev libxslt-dev # e.g. Ubuntu/Debian sudo gem install sax-machine |
今回はLast.fm APIで試すので、Last.fmにユーザ登録し、API KEYを取得する。API Accountへ。
コード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | require 'rubygems' require 'sax-machine' require 'open-uri' module Lastfm class Track include SAXMachine element :name element :artist element :url element :streamable element :listeners ["small", "medium", "large", "extralarge"].each do |size| element :image, :as => "image_#{size}", :with => {:size => size} end end class TrackInfo include SAXMachine element "opensearch:Query", :value => :searchTerms, :as => :query element "opensearch:Query", :value => :role, :as => :query element "opensearch:totalResults", :as => :total_results element "opensearch:startIndex", :as => :start element "opensearch:itemsPerPage", :as => :per_page elements :track, :as => :tracks, :class => Track class << self API_KEY = "YOUR_API_KEY" PER_PAGE = 5 def search(query, options={}) # 検索インタフェース page = (options[:page] || 1).to_i per_page = (options[:per_page] || PER_PAGE).to_i url = URI.encode( "http://ws.audioscrobbler.com/2.0/?" + "method=track.search&" + "track=#{query}&" + "api_key=#{API_KEY}&" + "limit=#{per_page}&" + "page=#{page}" ) parse(open(url)) end end end end lastfm = Lastfm::TrackInfo.search("夏") #=> #<Lastfm::TrackInfo:0x7f8d664d97e8> lastfm.total_results #=> 380 lastfm.tracks.count #=> 5 puts lastfm.tracks[0].name # 夏・コイ puts lastfm.tracks[0].artist # いきものがかり |
Last.fmのAPI解説ページからたどれる実際のXMLと、比較するといいと思います。
sax-machineでやれること
- 要素の中身を取得する。
- 要素の中身を別名をつけて取得する。
- 要素の属性を取得する。それも、別々に取れる。
- 特定の属性を持った要素の中身を取得する。
- 複数の要素を取得する。
- 入れ子された要素については、新たな、SAXMachineをincludeしたクラスに変換できる。
- 不要な要素は無視できる。
なお、複数要素取得については、
1 2 3 4 5 6 7 | <xml> <hoge /> <fuga /> <item>......</item> <item>......</item> <item>......</item> </xml> |
も、
1 2 3 4 5 6 7 8 9 | <xml> <hoge /> <fuga /> <list> <item>......</item> <item>......</item> <item>......</item> </list> </xml> |
も、同じように elements :item, :as => :items で取得可能です。SAXだから階層の深さが関係ない(、ということのはず)です。
あと、要素の中身をIntegerにするとかDateTimeにするとかはできません。。
かなり使いでがいいです。まだRuby向けライブラリができてないような、REST/XMLベースのAPIを使う際には、試してみてはいかがでしょう?
Pingback: Tweets that mention udzura1984: sax-machine、地味に使えるXMLパーサなので押してます [ruby] -- Topsy.com