library rss

[edit]

要約

RSS を扱うためのライブラリです。

参考

注意

RSS ParserはRSS 0.9x/1.0/2.0, Atom 1.0 をサポートしていますが,RSS 0.90 はサポートしてません.ごめんなさい.

RSS のモジュールはそれぞれ、

をサポートしています。ただし,Content モジュールは content:encoded しかサポートしていません.

パース

RSS をパースしたい場合は RSS::Parser クラスを使います。 RSS::Parser.parse は String の RSSを パースします(使用するXMLパーサによっては File や IO オブジェクトなどでもパース可能です)。

をそれぞれ返します。パースした 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を出力する流れは以下のようになります.

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

例えば,

を生成するには以下のようにします.

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

もし,

エントリを含めたければ以下のようにします.

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

更新時刻を追加

もし,先のエントリが

のものならこうします.

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=の単なる別名です.

さらにエントリを追加

さらに,

エントリを持つなら以下のようにします.

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

ロゴの指定

もし,サイトに

がある場合は以下のようにします.

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

検索ページの指定

もし,

検索用ページがあったら以下のようにします.

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スタイルシートの指定

もし,

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なら以下のようになります。

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はそれぞれ以下を返します。

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::Element
  RSS::ImageFaviconModel::ImageFavicon
  RSS::ImageItemModel::ImageItem
  RSS::RDF
  RSS::RDF::Channel
  RSS::RDF::Channel::Image
  RSS::RDF::Channel::ImageFavicon
  RSS::RDF::Channel::Items
  RSS::RDF::Channel::Textinput
  RSS::RDF::Image
  RSS::RDF::Item
  RSS::RDF::Textinput
  RSS::Rss
  RSS::Rss::Channel
  RSS::Rss::Channel::Cloud
  RSS::Rss::Channel::Image
  RSS::Rss::Channel::Item
  RSS::Rss::Channel::Item::Category
  RSS::Rss::Channel::Item::Enclosure
  RSS::Rss::Channel::Item::Guid
  RSS::Rss::Channel::Item::Source
  RSS::Rss::Channel::TextInput
  RSS::Rss::SkipDays
  RSS::Rss::SkipHours
  RSS::TaxonomyTopicModel::TaxonomyTopic
  RSS::TaxonomyTopicsModel::TaxonomyTopics
  RSS::TrackBackModel10::TrackBackAbout
  RSS::TrackBackModel10::TrackBackPing
  RSS::TrackBackModel20::TrackBackAbout
  RSS::TrackBackModel20::TrackBackPing
RSS::Maker::Base
  RSS::Maker::ItemsBase
   RSS::Maker::RSS09::Items
    RSS::Maker::RSS20::Items
   RSS::Maker::RSS10::Items
  RSS::Maker::ItemsBase::ItemBase::EnclosureBase
   RSS::Maker::RSS09::Items::Item::Enclosure
    RSS::Maker::RSS20::Items::Item::Enclosure

RSS 2.0を生成するときだけ利用されます.

  RSS::Maker::ItemsBase::ItemBase::GuidBase
   RSS::Maker::RSS09::Items::Item::Guid
    RSS::Maker::RSS20::Items::Item::Guid

RSS 2.0を生成するときだけ利用されます.

  RSS::Maker::ItemsBase::ItemBase::SourceBase
   RSS::Maker::RSS09::Items::Item::Source
    RSS::Maker::RSS20::Items::Item::Source

RSS 2.0を生成するときだけ利用されます.

RSS::Maker::ChannelBase

channel要素の値を設定します.

  RSS::Maker::RSS09::Channel
   RSS::Maker::RSS20::Channel
  RSS::Maker::RSS10::Channel
RSS::Maker::ChannelBase::CategoriesBase
  RSS::Maker::RSS09::Channel::Categories
   RSS::Maker::RSS20::Channel::Categories
  RSS::Maker::RSS10::Channel::Categories
RSS::Maker::ChannelBase::CategoriesBase::CategoryBase

categoryは maker.channel.categories.new_categoryで作成されたオブジェクトとします.

  RSS::Maker::RSS09::Channel::Categories::Category
   RSS::Maker::RSS20::Channel::Categories::Category
  RSS::Maker::RSS10::Channel::Categories::Category
RSS::Maker::ChannelBase::SkipDaysBase

RSS 0.91/2.0を生成するときだけ利用されます.

  RSS::Maker::RSS09::Channel::SkipDays
   RSS::Maker::RSS20::Channel::SkipDays
RSS::Maker::ChannelBase::SkipDaysBase::DayBase

dayは maker.channel.skipDays.new_dayで作成されたオブジェクトとします.

  RSS::Maker::RSS09::Channel::SkipDays::Day
   RSS::Maker::RSS20::Channel::SkipDays::Day
RSS::Maker::ChannelBase::SkipHoursBase
  RSS::Maker::RSS09::Channel::SkipHours
   RSS::Maker::RSS20::Channel::SkipHours
RSS::Maker::ChannelBase::SkipHoursBase::HourBase

hourは maker.channel.skipHours.new_hourで作成されたオブジェクトとします.

  RSS::Maker::RSS09::Channel::SkipHours::Hour
   RSS::Maker::RSS20::Channel::SkipHours::Hour
RSS::Maker::ImageBase

RSS 1.0の場合はurl,title, maker.channel.link,maker.channelが適切に設定されている必要があります.

  RSS::Maker::RSS09::Image
   RSS::Maker::RSS20::Image
  RSS::Maker::RSS10::Image
RSS::Maker::ItemsBase::ItemBase

itemはmaker.items.new_itemで作成されたオブジェクトとします.

  RSS::Maker::RSS09::Items::Item
   RSS::Maker::RSS20::Items::Item
  RSS::Maker::RSS10::Items::Item
RSS::Maker::ItemsBase::ItemBase::CategoriesBase
  RSS::Maker::RSS09::Items::Item::Categories
   RSS::Maker::RSS20::Items::Item::Categories

RSS 2.0を生成するときだけ利用されます.

RSS::Maker::RSSBase

RSSのルート要素を生成するオブジェクトです.

  RSS::Maker::RSS10
  RSS::Maker::RSS20
RSS::Maker::TextinputBase

RSS 1.0の場合はtitle,description,name, link,maker.channelを適切に設定する必要があります.

  RSS::Maker::RSS09::Textinput
   RSS::Maker::RSS20::Textinput
  RSS::Maker::RSS10::Textinput
RSS::Maker::XMLStyleSheets::XMLStyleSheet

xml_stylesheetは maker.xml_stylesheet.new_xml_stylesheetで作成されたオブジェクトとします.

RSS::Parser
RSS::XMLStyleSheet

モジュール

DublinCoreModel
RSS::BaseTrackBackModel
RSS::ContentModel
RSS::DublinCoreModel

@todo

RSS::ImageFaviconModel
RSS::ImageItemModel
RSS::ImageModelUtils

@todo

RSS::Maker
RSS::RootElementMixin
RSS::SyndicationModel
RSS::TaxonomyTopicModel
RSS::TaxonomyTopicsModel
RSS::TrackBackModel10
RSS::TrackBackModel20
RSS::XMLStyleSheetMixin

例外クラス

RSS::Error
  RSS::ConversionError
  RSS::InvalidRSSError
   RSS::MissingAttributeError
   RSS::MissingTagError
   RSS::NotAvailableValueError
   RSS::NotExpectedTagError
   RSS::TooMuchTagError
   RSS::UnknownTagError
  RSS::NSError
  RSS::NotSetError
  RSS::NotValidXMLParser
  RSS::NotWellFormedError
  RSS::OverlappedPrefixError
  RSS::UnknownConversionMethodError
  RSS::XMLParserNotFound

追加・再定義されるメソッド

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=