要約
RSS を扱うためのライブラリです。
参考
- RSS 0.91 http://backend.userland.com/rss091
- RSS 1.0 http://purl.org/rss/1.0/spec
- RSS 2.0 http://www.rssboard.org/rss-specification
- Atom 1.0 https://www.ietf.org/rfc/rfc4287.txt
注意
RSS ParserはRSS 0.9x/1.0/2.0, Atom 1.0 をサポートしていますが,RSS 0.90 はサポートしてません.ごめんなさい.
RSS のモジュールはそれぞれ、
- Dublin Core モジュール http://web.resource.org/rss/1.0/modules/dc/
- Syndication モジュール http://web.resource.org/rss/1.0/modules/syndication/
- Content モジュール http://web.resource.org/rss/1.0/modules/content/
- Trackback モジュール http://madskills.com/public/xml/rss/module/trackback/
- Image モジュール http://web.resource.org/rss/1.0/modules/image/
をサポートしています。ただし,Content モジュールは content:encoded しかサポートしていません.
パース
RSS をパースしたい場合は RSS::Parser クラスを使います。 RSS::Parser.parse は String の RSSを パースします(使用するXMLパーサによっては File や IO オブジェクトなどでもパース可能です)。
- RSS 1.0をパースした場合は RSS::RDF オブジェクト
- RSS 0.9x/2.0をパースした場合は RSS::Rss オブジェクト
- Atom をパースした場合は RSS::Atom::Feed オブジェクト
をそれぞれ返します。パースした String が well formed な XML で無い場合は,例外 RSS::NotWellFormedError が発生します。well formed な XML だが,RSS 0.9x/1.0/2.0, Atom のいずれでもない場合は,nil が返ります.
例えば、RSS 1.0 をバリデーション付きでパースするには以下のようにします。ここで、変数 rss_source には RSS 1.0 形式の文字列が格納されているものとします。
require 'rss' rss = RSS::Parser.parse(rss_source, true)
RSS::Parser.parse の第二引数は省略すると true が指定されたものとみなされるので、これは以下のようにも書けます。
require 'rss' rss = RSS::Parser.parse(rss_source)
最初はバリデーション付きでパースして,valid ではない RSS だった場合はバリデーション無しでパースするには以下のように書きます。
require 'rss' rss = nil begin rss = RSS::Parser.parse(rss_source) rescue RSS::InvalidRSSError rss = RSS::Parser.parse(rss_source, false) end
これは rss_source が RSS 0.9x/1.0/2.0 のどれか分からない時にも有効です。RSS 1.0としてバリデーション付きでパースし、バリデーションに失敗すると RSS 0.9x/(壊れた)1.0/2.0 のいずれかとしてパースします。
知らない要素の扱い
パーサはデフォルトでは知らない要素(仕様書に規定されていない要素)を無視します。もし、知らない要素に遭遇した時に例外を発生させたければ,RSS::Parser.parse の第三引数に false を指定してください。こうすると、パース中に知らない要素に遭遇した時に RSS::UnknownTagError 例外が発生します。RSS::UnknownTagError クラスは RSS::InvalidError クラスのサブクラスです。
以下のようにすると,より厳密にパースできます。
RSS::Parser.parse(rss_source, true, false)
パースされたフィード
フィードをパースすると RSS::RDF, RSS::RDF::Channel, RSS::Rss, RSS::Atom::Feed 等のオブジェクトになります。各オブジェクトで子要素オブジェクトにアクセスするために,要素名と同じ名前のアクセサがあります。
リーダ(reader)
rdf:RDF 要素の子要素である channel 要素を参照するには,以下のようにします。
rss = RSS::Parser.parse(rss_source) rss.channel # => /rdf:RDF/channel要素; RSS::RDF::Channel
もし、要素が子要素も属性も持たない場合は String が返ってきます。その要素が省略可能ならばnilが返って来るかもしれません。これは要素が子要素または属性を持つ場合も同様です。
rss = RSS::Parser.parse(rss_source) rss.channel.description # => /rdf:RDF/channel/text(); String
属性にアクセスする時も同様です。channel要素のrdf:about属性にアクセスするには以下のようにします。属性の値はStringかnilです。
rss = RSS::Parser.parse(rss_source) rss.channel.about # => /rdf:RDF/channel/@about属性; String または nil
同名の複数の子要素があるかもしれないときも同様です。ただし、リーダに引数を指定しないと最初の子要素が返ってきます。例えば、 rdf:RDF要素の最初のitem要素にアクセスするには以下のようにします。
rss = RSS::Parser.parse(rss_source) rss.item # => /rdf:RDF/item[1]要素; RSS::RDF::Item
3番目のitem要素にアクセスするには以下のようにします。省略されなかったリーダの引数はArray#[]の引数と同じように扱われます。
rss = RSS::Parser.parse(rss_source) rss.item(2) # => /rdf:RDF/item[3]要素; RSS::RDF::Item
子要素すべてを取得したいときは要素名の複数形がリーダとなります。すべてのitem要素を取得するには以下のようにします。
rss = RSS::Parser.parse(rss_source) rss.items # => /rdf:RDF/item要素の配列; [RSS::RDF::Item, ...]
ライタ(writer)
rdf:RDF要素の子要素であるchannel要素を設定するには以下のようにします。RSS::RDF::Channel.newの第一引数にはrdf:about属性の値を指定することもできます。
rss = RSS::Parser.parse(rss_source) rss.channel = RSS::RDF::Channel.new(rdf_about_value)
属性値を設定する場合も同様です。
rss = RSS::Parser.parse(rss_source) rss.channel.about = "http://cozmixng.www.cozmixng.org/"
同名の複数の子要素が存在する場合は少し異なります.要素名の複数形でのメソッドで要素の配列を取得して,その配列に対して Array#<<やArray#[]=などを用いて要素を設定します.
rss = RSS::Parser.parse(rss_source) item = RSS::RDF::Item.new(rdf_about_value) rss.items << item rss.items.last == item # => true
注意: item=/set_itemなどはRubyっぽくないので使わないでください.
出力
RSS Parserといっているので誤解されがちですが,RSS/Atomを出力することもできます.
基本
to_sするとRSSまたはAtom形式の文字列を返します.
RSS/Atomを出力する流れは以下のようになります.
- RSS/Atomオブジェクト(RSS::RDFとかRSS::Rssクラスとか RSS::Atom::Feedのオブジェクト)を作成する
- 出力エンコーディングを指定する(省略可)
- RSSオブジェクトのto_sメソッドを呼ぶ
xml-stylesheet
xml-stylesheetも出力することができます.
RSSのルート要素(RSS::RDFまたはRSS::Rss)オブジェクトおよびAtomのルート要素(RSS::Atom::Feedまたは RSS::Atom::Entry)オブジェクトはxml_stylesheetsという名前の配列を持っています.この配列にRSS::XMLStyleSheet オブジェクトを挿入することでRSS/Atomにxml-stylesheetを関連づけることができます.
rss.xml_stylesheets << RSS::XMLStyleSheet.new(...)
RSS::XMLStyleSheet.newには以下のようなHashまたは連想配列を渡します.作成されるRSS::XMLStyleSheetオブジェクトは与えられた引数によって初期化されます.
Hash:
{ :href => "...", :type => "...", :title => "...", :media => "...", :charset => "...", :alternate => "...", }
連想配列:
[ [:href, "..."], [:type, "..."], [:title, "..."], [:media, "..."], [:charset, "..."], [:alternate, "..."], ]
全てのキーは省略可能です.
例えば,xml-stylesheetとしてsample.xslを指定する場合は以下のようにします.
rss.xml_stylesheets << RSS::XMLStyleSheet.new({:href => "sample.xsl"})
本当は{:type => "text/xsl"}も指定しないといけないところですが,拡張子が.xslまたは,.cssの場合は適当に推測してくれるので省略可能です.
RSS/Atomオブジェクトを作る
既存のRSS/Atomをパースせずに,一から新しくRSS/Atomを作成するには RSS Makerが便利です.
以下のように使います.
require "rss" rss = RSS::Maker.make("バージョン") do |maker| maker.XXX = YYY ... end
シンプルなRSS
例えば,
- http://example.com/にある
- Example Siteという説明文を持つ
- Exampleというサイトを
- http://example.com/index.rdfという名前のRSS 1.0
を生成するには以下のようにします.
require "rss" rss = RSS::Maker.make("1.0") do |maker| maker.channel.about = "http://example.com/index.rdf" maker.channel.title = "Example" maker.channel.description = "Example Site" maker.channel.link = "http://example.com/" end
もし,
- http://example.com/article.htmlにある
- Sample Articleというタイトルの
エントリを含めたければ以下のようにします.
require "rss" rss = RSS::Maker.make("1.0") do |maker| maker.channel.about = "http://example.com/index.rdf" maker.channel.title = "Example" maker.channel.description = "Example Site" maker.channel.link = "http://example.com/" item = maker.items.new_item item.link = "http://example.com/article.html" item.title = "Sample Article" end
更新時刻を追加
もし,先のエントリが
- 2004/11/1 10:10
のものならこうします.
require "rss" rss = RSS::Maker.make("1.0") do |maker| maker.channel.about = "http://example.com/index.rdf" maker.channel.title = "Example" maker.channel.description = "Example Site" maker.channel.link = "http://example.com/" maker.items.new_item do |item| item.link = "http://example.com/article.html" item.title = "Sample Article" item.date = Time.parse("2004/11/1 10:10") end end
サンプル中の
item.date = ...
は
item.dc_date = ...
でも構いません.#dc_date=は#date=の単なる別名です.
さらにエントリを追加
さらに,
- http://example.com/article2.htmlにある
- Sample Article2という
- 2004/11/2 10:10に作成された
エントリを持つなら以下のようにします.
require "rss" rss = RSS::Maker.make("1.0") do |maker| maker.channel.about = "http://example.com/index.rdf" maker.channel.title = "Example" maker.channel.description = "Example Site" maker.channel.link = "http://example.com/" maker.items.new_item do |item| item.link = "http://example.com/article.html" item.title = "Sample Article" item.date = Time.parse("2004/11/1 10:10") end maker.items.new_item do |item| item.link = "http://example.com/article2.html" item.title = "Sample Article2" item.date = Time.parse("2004/11/2 10:10") end end
エントリを並び替える
もし,更新日が新しい順に並び替えたければ
maker.items.do_sort = true
を追加し,以下のようにします.
require "rss" rss = RSS::Maker.make("1.0") do |maker| maker.channel.about = "http://example.com/index.rdf" maker.channel.title = "Example" maker.channel.description = "Example Site" maker.channel.link = "http://example.com/" maker.items.do_sort = true maker.items.new_item do |item| item.link = "http://example.com/article.html" item.title = "Sample Article" item.date = Time.parse("2004/11/1 10:10") end maker.items.new_item do |item| item.link = "http://example.com/article2.html" item.title = "Sample Article2" item.date = Time.parse("2004/11/2 10:10") end end
ロゴの指定
もし,サイトに
- Example Siteという名前の
- http://example.com/logo.pngというロゴ
がある場合は以下のようにします.
require "rss" rss = RSS::Maker.make("1.0") do |maker| maker.channel.about = "http://example.com/index.rdf" maker.channel.title = "Example" maker.channel.description = "Example Site" maker.channel.link = "http://example.com/" maker.items.do_sort = true maker.items.new_item do |item| item.link = "http://example.com/article.html" item.title = "Sample Article" item.date = Time.parse("2004/11/1 10:10") end maker.items.new_item do |item| item.link = "http://example.com/article2.html" item.title = "Sample Article2" item.date = Time.parse("2004/11/2 10:10") end maker.image.title = "Example Site" maker.image.url = "http://example.com/logo.png" end
検索ページの指定
もし,
- http://example.com/search.cgiに
- keywordというパラメタ名で検索できる
- Search Example Siteという名前で
- Search Example Site's all textという説明付きの
検索用ページがあったら以下のようにします.
require "rss" rss = RSS::Maker.make("1.0") do |maker| maker.channel.about = "http://example.com/index.rdf" maker.channel.title = "Example" maker.channel.description = "Example Site" maker.channel.link = "http://example.com/" maker.items.do_sort = true maker.items.new_item do |item| item.link = "http://example.com/article.html" item.title = "Sample Article" item.date = Time.parse("2004/11/1 10:10") end maker.items.new_item do |item| item.link = "http://example.com/article2.html" item.title = "Sample Article2" item.date = Time.parse("2004/11/2 10:10") end maker.image.title = "Example Site" maker.image.url = "http://example.com/logo.png" maker.textinput.title = "Search Example Site" maker.textinput.description = "Search Example Site's all text" maker.textinput.name = "keyword" maker.textinput.link = "http://example.com/search.cgi" end
XMLスタイルシートの指定
もし,
- http://example.com/index.xslにある
xml-stylesheetを追加したい場合は以下のようにします.
require "rss" rss = RSS::Maker.make("1.0") do |maker| xss = maker.xml_stylesheets.new_xml_stylesheet xss.href = "http://example.com/index.xsl" maker.channel.about = "http://example.com/index.rdf" maker.channel.title = "Example" maker.channel.description = "Example Site" maker.channel.link = "http://example.com/" maker.items.do_sort = true maker.items.new_item do |item| item.link = "http://example.com/article.html" item.title = "Sample Article" item.date = Time.parse("2004/11/1 10:10") end maker.items.new_item do |item| item.link = "http://example.com/article2.html" item.title = "Sample Article2" item.date = Time.parse("2004/11/2 10:10") end maker.image.title = "Example Site" maker.image.url = "http://example.com/logo.png" maker.textinput.title = "Search Example Site" maker.textinput.description = "Search Example Site's all text" maker.textinput.name = "keyword" maker.textinput.link = "http://example.com/search.cgi" end
RSS 2.0の生成
もし,RSS 2.0を生成したい場合は以下のように, RSS::Maker.makeの第一引数を変更します.
require "rss" rss = RSS::Maker.make("2.0") do |maker| xss = maker.xml_stylesheets.new_xml_stylesheet xss.href = "http://example.com/index.xsl" maker.channel.about = "http://example.com/index.rdf" maker.channel.title = "Example" maker.channel.description = "Example Site" maker.channel.link = "http://example.com/" maker.items.do_sort = true maker.items.new_item do |item| item.link = "http://example.com/article.html" item.title = "Sample Article" item.date = Time.parse("2004/11/1 10:10") end maker.items.new_item do |item| item.link = "http://example.com/article2.html" item.title = "Sample Article2" item.date = Time.parse("2004/11/2 10:10") end maker.image.title = "Example Site" maker.image.url = "http://example.com/logo.png" maker.textinput.title = "Search Example Site" maker.textinput.description = "Search Example Site's all text" maker.textinput.name = "keyword" maker.textinput.link = "http://example.com/search.cgi" end
RSS 0.91の生成
もし,RSS 0.91を生成したい場合は,RSS 2.0の場合と同様に RSS::Maker.make の第一引数を"0.91"に変更します.
ただし、RSS 0.91では言語指定が必須なので、言語を指定する必要があります。ここでは日本語であると指定します。
rss = RSS::Maker.make("0.91") do |maker| maker.channel.language = "ja" ... end
RSS 1.0など、/rdf:RDF/channel/language要素がないフィードの場合でも、単に無視したりdc:languageとして扱ったりと適切に処理します。そのため、以下のように「バージョンが"0.91"のときだけ言語を指定する」というように書く必要はありません。フィードのバージョンに関わらず言語を指定してください。
rss = RSS::Maker.make("0.91") do |maker| maker.channel.language = "ja" if maker.feed_version == "0.91" ... end
Atom 1.0の生成
もし,Atom 1.0を生成したい場合は,RSS 0.91や2.0の場合と同様に RSS::Maker.makeの第一引数を"atom"に変更します.
rss = RSS::Maker.make("atom") do |maker| ... end
ただし、これだけでは十分ではありません。これは、Atom 1.0では RSS 1.0/2.0/0.91では必須ではなかった以下の情報が必要となるからです。
- このAtom 1.0の作者
- このAtom 1.0の更新日
よって、これまでのスクリプトをAtom 1.0を出力するようにするためには以下のように変更する必要があります。
- RSS::Maker.makeの第一引数を"atom"に変更
- maker.channel.authorを設定
- maker.channel.dateを設定
もし、
- 作者がBobで
- たった今、作成された
Atom 1.0なら以下のようになります。
require "rss" atom = RSS::Maker.make("atom") do |maker| xss = maker.xml_stylesheets.new_xml_stylesheet xss.href = "http://example.com/index.xsl" maker.channel.about = "http://example.com/atom.xml" maker.channel.title = "Example" maker.channel.description = "Example Site" maker.channel.link = "http://example.com/" maker.channel.author = "Bob" maker.channel.date = Time.now maker.items.do_sort = true maker.items.new_item do |item| item.link = "http://example.com/article.html" item.title = "Sample Article" item.date = Time.parse("2004/11/1 10:10") end maker.items.new_item do |item| item.link = "http://example.com/article2.html" item.title = "Sample Article2" item.date = Time.parse("2004/11/2 10:10") end maker.image.title = "Example Site" maker.image.url = "http://example.com/logo.png" maker.textinput.title = "Search Example Site" maker.textinput.description = "Search Example Site's all text" maker.textinput.name = "keyword" maker.textinput.link = "http://example.com/search.cgi" end
Atom 1.0用の情報を加えたこのスクリプトを最初のRSS 1.0を出力するスクリプトに戻す場合は、RSS::Maker.makeの第一引数を"1.0"に変えるだけです。Atom 1.0用に追加した情報を削除する必要はありません。それらは単に無視されます。
RSS/Atomオブジェクトを変換する
フィードの種類がRSS 1.0/2.0でもAtomでもパースするためのAPIは以下のように共通です。
feed = RSS::Parser.parse(feed_xml)
しかし、返ってくるオブジェクトはRSS 1.0オブジェクト(RSS::RDF)かもしれませんし、Atomオブジェクト(RSS::Atom::Feed)かもしれません。このため、パースした結果を使う場合はフィードの種類を意識しなくてはならず、使いづらくなります。
RSS Parserが提供する解決方法はユーザに好みのフィードの種類を選んでもらうというものです。例えば、以下のようにしてRSS 1.0 をRSS 2.0に変換することができます。
require 'rss' rss10 = RSS::Parser.parse(rss10_xml) rss20 = rss10.to_feed("rss2.0")
種類がわからない複数のフィードを扱う場合は以下のようにし、すべてのフィードをRSS 2.0のように扱うことができます。
feeds.each do |xml| rss20 = RSS::Parser.parse(xml).to_feed("rss2.0") ... end
また、to_feedは以下のように書くことも出来ます。
feed.to_rss("1.0") # == feed.to_feed("rss1.0") feed.to_rss("2.0") # == feed.to_feed("rss2.0") feed.to_atom("1.0") # == feed.to_feed("atom1.0")
形式を変換したときに問題になるのは、変換元のオブジェクトが変換後の形式に必須の情報を持っていない場合です。この場合は変換に失敗します(RSS::Errorのサブクラスの例外が発生します)。そのため、適宜、必要な情報を補う必要があります。たとえば、RSS 1.0では各item要素にタイトルが必須ですが、RSS 2.0では省略可能です。そのような場合に対応するために、以下のようにブロックを使用することが出来ます。
rss10 = feed.to_rss("1.0") do |maker| maker.items.each do |item| item.title.content ||= "No title" end end
to_feedのブロック内で出来ることを理解するためには、to_feedがどのように動作するかを理解するとよいです。パース結果のオブジェクトはフィードの種類に関わらずsetup_makerというメソッドを持っています。これは、自分が持っている情報をRSS Makerに与えるメソッドです。to_feedはRSS::Maker.makeで作ったRSS Makerに対して setup_makerを行い、他の形式に変換しようとします。ブロックには setup_makerを行った後のRSS Makerが渡されます。つまり、 to_feedのブロック内で出来ることはRSS Makerに対して出来ることと同じです。
フィードの形式を変換する
上記の方法でパース済みのオブジェクトを変換できるので、フィードを異なる形式のXMLへ変換することは簡単です。
feed = RSS::Parser.parse(feed_xml) new_feed_xml = feed.to_feed("atom1.0").to_s
これを行うための便利なメソッドto_xmlがあります。to_xmlを使うと以下のように書き直すことができます。
feed = RSS::Parser.parse(feed_xml) new_feed_xml = feed.to_xml("atom1.0")
。。。あまり変わりませんね。to_feedを用いた場合と同じようにブロックを指定してRSS Makerを操作することも出来ます。ますます変わりませんね。
to_feed().to_sではなく、to_xmlを使うことには一長一短があります。to_xmlは変換元のフィードの種類と変換後のフィードの種類が同じ場合は単にto_sを呼び出すだけです。これにより、同じ形式に変換する場合の速度があがります(RSS Makerを作って変換、ということを省略するので当然です)。しかし、ブロックを指定して変換後の結果を調整することができません。例えば、以下のようにRSS 1.0からRSS 2.0に変換する場合はブロックが呼ばれます。
rss10.to_xml("rss2.0") do |maker| # makerを操作できる end
しかし、以下のようにRSS 1.0からRSS 1.0に変換しようとした場合はブロックは呼び出されません。
rss10.to_xml("rss1.0") do |maker| # ブロックが呼び出されないのでmakerを操作できない。 end
このAPIに関しては、どうしたらよいのかまだ悩んでいます。もし、なにかアイディアがあれば教えてください。
サンプル
RSS Parser のサンプルスクリプトをいくつか紹介します.これらのスクリプトは sample/ 以下に入っています.
サンプル1 - 項目一覧
それでは、複数のフィードをパースしてitem要素を表示するスクリプトを書いてみましょう。
まず、RSS 0.9x/1.0/2.0, Atom 1.0をパースできるように以下のようにrequireします。
require 'rss'
パースするフィードはファイルに保存されていて引数で与えられるものとします。
ARGV.each do |fname| feed = nil begin feed = RSS::Parser.parse(File.read(fname), false) rescue RSS::Error end if feed.nil? puts "#{fname}はRSS 0.9x/1.0/2.0, Atom 1.0のいずれでもありません。" else print_items(feed) end end
あとはprint_itemsというメソッドを定義するだけです。
RSS::RDF/RSS::Rss/RSS::Atom::Feed/RSS::Atom::Entryには便利のためにitemsというメソッドとimageというメソッドが定義されています。
itemsはそれぞれ以下を返します。
- RSS::RDF: 全ての/rdf:RDF/item要素の配列
- RSS::Rss: 全ての/rss/channel/item要素の配列
- RSS::Atom::Feed: 全ての/atom:feed/atom:entry要素の配列
- RSS::Atom::Entry: /atom:entry要素のみが含まれる配列
imageはそれぞれ以下を返します。
- RSS::RDF: /rdf:RDF/image要素
- RSS::Rss: /rss/channel/image要素
ここでは、itemsを使って各項目を表示します。
def print_items(feed) feed.items.each do |item| puts "#{item.title} : #{item.description}" end end
これは、RSSフィードに対してはうまく動きますが、Atomフィードに対してはうまく動きません。それはAtomフィードにはdescription要素がないからです。そこで、AtomフィードもRSSフィードに変えて扱うことにします。
def print_items(feed) convert_to_rss10(feed).items.each do |item| puts "#{item.title} : #{item.description}" end end
convert_to_rss10は以下のようになります。
def convert_to_rss10(feed) feed.to_rss("1.0") do |maker| maker.channel.about ||= maker.channel.link maker.channel.description.content ||= "No description" maker.items.each do |item| item.title.content ||= "No title" item.link ||= "UNKNOWN" end end end
未設定の可能性がある要素にデフォルト値を設定しています。
出力する文字コードを変更するにはoutput_encoding=が使えます。もし、変換できないエンコーディングを指定された場合は RSS::UnknownConversionMethodError例外が発生します。
先程のprint_itemsをEUC-JPで出力するように書き換えてみましょう。
def print_items(feed) rss10 = convert_to_rss10(feed) begin rss10.output_encoding = "EUC-JP" rescue RSS::UnknownConversionMethodError end rss10.items.each do |item| puts "#{item.title} : #{item.description}" end end
サンプル2 - 更新順表示
次はDublin Coreモジュールのdate属性を使って更新順にitemを表示してみましょう。
最初に現れたDublin Coreモジュールの要素にアクセスするには「dc_要素名」というアクセサが用意されています。全ての要素の配列にアクセスするには「dc_要素の複数形」(dc_rightsは dc_rights_listになります)とします.
複数形でアクセスした場合は「要素の内容を表す文字列」ではなく,「要素を表すオブジェクト」の配列が返ります.「要素を表すオブジェクト」から「要素の内容を表す文字列」を取得するには contentメソッドやその別名であるvalueメソッドを利用します.「要素の内容を表す文字列」を設定するには content=メソッドやその別名であるvalue=メソッドを利用します.
rss.channel.dc_title # => 「要素の内容を表す文字列」 # ("My site"など) rss.channel.dc_titles # => 「要素を表すオブジェクト」の配列 # ([DublinCoreTitleオブジェクト, ...]) rss.channel.dc_titles.collect {|title| title.value} # => 「要素の内容を表す文字列」の配列 # (["My site", ...]など) rss.channel.dc_titles.first.value == rss.channel.dc_title # => true # 厳密にはこう first_title = rss.channel.dc_titles.first first_title = first_title.value if first_title first_title == rss.channel.dc_title # => true
ちなみにSyndicationモジュールの要素にアクセスするには「sy_要素名」というアクセサが,Contentモジュールの要素にアクセスするには「content_要素名」というアクセサが用意されています。
サンプル1と同じようにパースするRSSはファイルに保存されていて引数で与えられるものとします。
require 'rss' items = [] ARGV.each do |fname| rss_source = nil File.open(fname) do |f| rss_source = f.read end rss = nil begin rss = RSS::Parser.parse(rss_source, true) rescue RSS::Error end if rss.nil? puts "#{fname}はRSS 1.0ではありません。" else begin rss.output_encoding = "euc-jp" rescue RSS::UnknownConversionMethodError end rss.items.each do |item| items << item if item.dc_date end end end print_items(items)
あとはprint_itemsというメソッドを定義するだけです。
Item#dc_dateはTimeオブジェクトかnilを返します。引数の itemsにはdc_dateがnilではないものしか含まれていないはずなので以下のようにソートできます。
def print_items(items) items.sort do |x, y| y.dc_date <=> x.dc_date end.each do |item| puts "#{item.dc_date.localtime.iso8601} : #{item.title} : #{item.description}" end end
クラス
モジュール
例外クラス
追加・再定義されるメソッド
RSS::Rss::Channel#generator
RSS::Rss::Channel#generator=
RSS::Rss::Channel#ttl
RSS::Rss::Channel#ttl=
RSS::Rss::Channel::Item#author
RSS::Rss::Channel::Item#author=
RSS::Rss::Channel::Item#comments
RSS::Rss::Channel::Item#comments=
RSS::Rss::Channel::Item#guid
RSS::Rss::Channel::Item#guid=
RSS::Rss::Channel::Item#pubDate
RSS::Rss::Channel::Item#pubDate=