requires=
classes=RSS=Rss,RSS=Rss=Channel,RSS=Rss=SkipDays,RSS=Rss=SkipHours,RSS=Rss=Channel=Image,RSS=Rss=Channel=Cloud,RSS=Rss=Channel=Item,RSS=Rss=Channel=Item=Source,RSS=Rss=Channel=Item=Enclosure,RSS=Rss=Channel=Item=Category,RSS=Rss=Channel=TextInput,RSS=RDF,RSS=ImageModelUtils,RSS=DublinCoreModel,RSS=RDF=Channel,RSS=RDF=Channel=Image,RSS=RDF=Channel=Textinput,RSS=RDF=Channel=Items,RSS=RDF=Channel=ImageFavicon,RSS=RDF=Image,RSS=RDF=Textinput,RSS=RDF=Item,RSS=Rss=Channel=Item=Guid,DublinCoreModel,RSS=SyndicationModel,RSS=TaxonomyTopicModel,RSS=TaxonomyTopicModel=TaxonomyTopic,RSS=TaxonomyTopicsModel,RSS=TaxonomyTopicsModel=TaxonomyTopics,RSS=ImageItemModel,RSS=ImageItemModel=ImageItem,RSS=ImageFaviconModel,RSS=ImageFaviconModel=ImageFavicon,RSS=BaseTrackBackModel,RSS=TrackBackModel10,RSS=TrackBackModel10=TrackBackPing,RSS=TrackBackModel10=TrackBackAbout,RSS=TrackBackModel20,RSS=TrackBackModel20=TrackBackPing,RSS=TrackBackModel20=TrackBackAbout,RSS=ContentModel,RSS=XMLStyleSheet,RSS=XMLStyleSheetMixin,RSS=Maker=ChannelBase=CategoriesBase,RSS=Maker=ItemsBase=ItemBase=CategoriesBase,RSS=Maker=ChannelBase=CategoriesBase=CategoryBase,RSS=Maker=RSS09=Channel=Categories,RSS=Maker=RSS10=Channel=Categories,RSS=Maker=RSS20=Channel=Categories,RSS=Maker=RSS09=Channel=Categories=Category,RSS=Maker=RSS10=Channel=Categories=Category,RSS=Maker=RSS20=Channel=Categories=Category,RSS=Maker=ChannelBase,RSS=Maker=RSS09=Channel,RSS=Maker=RSS10=Channel,RSS=Maker=RSS20=Channel,RSS=Maker,RSS=Maker=RSSBase,RSS=Maker=RSS10,RSS=Maker=RSS20,RSS=Maker=XMLStyleSheets=XMLStyleSheet,RSS=Maker=ChannelBase=SkipDaysBase,RSS=Maker=RSS09=Channel=SkipDays,RSS=Maker=RSS20=Channel=SkipDays,RSS=Maker=ChannelBase=SkipDaysBase=DayBase,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,RSS=Maker=RSS09=Channel=SkipHours=Hour,RSS=Maker=RSS20=Channel=SkipHours=Hour,RSS=Maker=ImageBase,RSS=Maker=RSS09=Image,RSS=Maker=RSS10=Image,RSS=Maker=RSS20=Image,RSS=Maker=Base,RSS=Maker=ItemsBase,RSS=Maker=RSS09=Items,RSS=Maker=RSS10=Items,RSS=Maker=RSS20=Items,RSS=Maker=ItemsBase=ItemBase,RSS=Maker=RSS09=Items=Item,RSS=Maker=RSS10=Items=Item,RSS=Maker=RSS20=Items=Item,RSS=Maker=ItemsBase=ItemBase=GuidBase,RSS=Maker=RSS09=Items=Item=Guid,RSS=Maker=RSS20=Items=Item=Guid,RSS=Maker=ItemsBase=ItemBase=EnclosureBase,RSS=Maker=RSS09=Items=Item=Enclosure,RSS=Maker=RSS20=Items=Item=Enclosure,RSS=Maker=ItemsBase=ItemBase=SourceBase,RSS=Maker=RSS09=Items=Item=Source,RSS=Maker=RSS20=Items=Item=Source,RSS=Maker=RSS09=Items=Item=Categories,RSS=Maker=RSS20=Items=Item=Categories,RSS=Maker=TextinputBase,RSS=Maker=RSS09=Textinput,RSS=Maker=RSS10=Textinput,RSS=Maker=RSS20=Textinput,RSS=Parser,RSS=NotWellFormedError,RSS=XMLParserNotFound,RSS=NotValidXMLParser,RSS=NSError,RSS=Element,RSS=RootElementMixin,RSS=Error,RSS=InvalidRSSError,RSS=OverlappedPrefixError,RSS=MissingTagError,RSS=TooMuchTagError,RSS=MissingAttributeError,RSS=UnknownTagError,RSS=NotExpectedTagError,RSS=NotAvailableValueError,RSS=UnknownConversionMethodError,RSS=ConversionError,RSS=NotSetError
methods=RSS=Rss=Channel/i.generator.rss,RSS=Rss=Channel/i.ttl.rss,RSS=Rss=Channel=Item/i.author.rss,RSS=Rss=Channel=Item/i.comments.rss,RSS=Rss=Channel=Item/i.pubDate.rss,RSS=Rss=Channel=Item/i.guid.rss
sublibraries=
is_sublibrary=false
category=FileFormat

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

=== 参考
  * [[url:http://www.cozmixng.org/~rwiki/?cmd=view;name=RSS+Parser]]
  * RSS 0.91 [[url:http://backend.userland.com/rss091]]
  * RSS 1.0  [[url:http://purl.org/rss/1.0/spec]]  
  * RSS 2.0  [[url:http://www.rssboard.org/rss-specification]]

=== 注意

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

RSS のモジュールはそれぞれ、
 * Dublin Core モジュール [[url:http://web.resource.org/rss/1.0/modules/dc/]] 
 * Syndication モジュール [[url:http://web.resource.org/rss/1.0/modules/syndication/]]
 * Content モジュール [[url:http://web.resource.org/rss/1.0/modules/content/]]
 * Trackback モジュール [[url:http://madskills.com/public/xml/rss/module/trackback/]]
 * Image モジュール [[url: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をパースした場合は [[c:RSS::RDF]] オブジェクト
 * RSS 0.9x/2.0をパースした場合は [[c:RSS::Rss]] オブジェクト
をそれぞれ返します。パースした
String が well formed な XML で無い場合は，
例外 [[c:RSS::NotWellFormedError]] が発生します。well formed な
XML だが，RSS 0.9x/1.0/2.0 のいずれでもない場合は，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 を指定して
ください。こうすると、パース中に知らない要素に遭遇した時に
[[c:RSS::UnknownTagError]] 例外が発生します。

以下のようにすると，より厳密にRSS 1.0をパースできます。

  RSS::Parser.parse(rss_source, true, false)

=== パースされたRSS

RSS はパースされると [[c:String]] オブジェクトから [[c:RSS::RDF]],
[[c:RSS::RDF::Channel]], [[c:RSS::Rss]] 等のオブジェクトになります。各オ
ブジェクトで子要素オブジェクトにアクセスするために，要素名と
同じ名前のアクセサがあります。

==== リーダ(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を出力する
こともできます．

==== 基本

to_sするとRSS形式の文字列を返します．

RSSを出力する流れは以下のようになります．

  * RSSオブジェクト（RSS::RDFとかRSS::Rssクラス
    のオブジェクト）を作成する

  * 出力エンコーディングを指定する(省略可)

  * RSSオブジェクトのto_sメソッドを呼ぶ

==== xml-stylesheet

xml-stylesheetも出力することができます．

RSSのルート要素（RSS::RDFまたはRSS::Rss）オブジェ
クトはxml_stylesheetsという名前の配列を持っています．この配
列にRSS::XMLStyleSheetオブジェクトを挿入することでRSS
に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オブジェクトを作る

既存のRSSをパースせずに，一から新しくRSSを作成するにはRSS
Makerが便利です．


以下のように使います．

  require "rss"

  rss = RSS::Maker.make("バージョン") do |maker|
    maker.XXX = YYY
    ...
  end

例えば，

  * 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/"

    item = maker.items.new_item
    item.link = "http://example.com/article.html"
    item.title = "Sample Article"
    item.date = Time.parse("2004/11/1 10:10")
  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/"

    item = maker.items.new_item
    item.link = "http://example.com/article.html"
    item.title = "Sample Article"
    item.date = Time.parse("2004/11/1 10:10")

    item = maker.items.new_item
    item.link = "http://example.com/article2.html"
    item.title = "Sample Article2"
    item.date = Time.parse("2004/11/2 10:10")
  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

    item = maker.items.new_item
    item.link = "http://example.com/article.html"
    item.title = "Sample Article"
    item.date = Time.parse("2004/11/1 10:10")

    item = maker.items.new_item
    item.link = "http://example.com/article2.html"
    item.title = "Sample Article2"
    item.date = Time.parse("2004/11/2 10:10")
  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

    item = maker.items.new_item
    item.link = "http://example.com/article.html"
    item.title = "Sample Article"
    item.date = Time.parse("2004/11/1 10:10")

    item = maker.items.new_item
    item.link = "http://example.com/article2.html"
    item.title = "Sample Article2"
    item.date = Time.parse("2004/11/2 10:10")

    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という説明付きの

検索用CGIがあったら以下のようにします．

  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

    item = maker.items.new_item
    item.link = "http://example.com/article.html"
    item.title = "Sample Article"
    item.date = Time.parse("2004/11/1 10:10")

    item = maker.items.new_item
    item.link = "http://example.com/article2.html"
    item.title = "Sample Article2"
    item.date = Time.parse("2004/11/2 10:10")

    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

もし，

  * 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

    item = maker.items.new_item
    item.link = "http://example.com/article.html"
    item.title = "Sample Article"
    item.date = Time.parse("2004/11/1 10:10")

    item = maker.items.new_item
    item.link = "http://example.com/article2.html"
    item.title = "Sample Article2"
    item.date = Time.parse("2004/11/2 10:10")

    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::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

    item = maker.items.new_item
    item.link = "http://example.com/article.html"
    item.title = "Sample Article"
    item.date = Time.parse("2004/11/1 10:10")

    item = maker.items.new_item
    item.link = "http://example.com/article2.html"
    item.title = "Sample Article2"
    item.date = Time.parse("2004/11/2 10:10")

    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 2.0の場合と同様に
RSS::Maker.make の第一引数を"0.91"に変更します．

=== サンプル

RSS Parser のサンプルスクリプトをいくつか紹介します．これらの
スクリプトは sample/ 以下に入っています．

==== サンプル1 - 項目一覧

それでは、複数のRSSをパースしてitem要素を表示するスクリプト
を書いてみましょう。

まず、RSS 0.9x/1.0/2.0をパースできるように以下のようにrequireします。

  require 'rss'

パースするRSSはファイルに保存されていて引数で与えられるものとします。

  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, false)
    rescue RSS::Error
    end

    if rss.nil?
      puts "#{fname}はRSS 0.9x/1.0/2.0のいずれでもありません。"
    else
      print_items(rss)
    end
  end

あとはprint_itemsというメソッドを定義するだけです。

RSS::RDFとRSS::Rssには便利のためにitemsというメソッドとimage
というメソッドが定義されています。

itemsはRSS::RDFの場合は全ての/rdf:RDF/item要素を配列で返しま
す。RSS::Rssの場合は全ての/rss/channel/item要素を配列で返し
ます。

imageはRSS::RDFの場合は/rdf:RDF/image要素を返します。
RSS::Rssの場合は/rss/channel/image要素を返します。

  def print_items(rss)
    rss.items.each do |item|
      puts "#{item.title} : #{item.description}"
    end
  end

出力する文字コードを変更するにはRSS::RDF#output_encoding=ま
たはRSS::Rss#output_encoding=が使えます。もし、変換できない
エンコーディングを指定された場合は
RSS::UnknownConversionMethodError例外が発生します。

先程のprint_itemsをEUC-JPで出力するように書き換えてみましょう。

  def print_items(rss)
    begin
      rss.output_encoding = "EUC-JP"
    rescue RSS::UnknownConversionMethodError
    end
    rss.items.each do |item|
      puts "#{item.title} : #{item.description}"
    end
  end



==== サンプル2 - 更新順表示

次はDublin Coreモジュールのdate属性を使って更新順にitemを表
示してみましょう。

最初に現れたDublin Coreモジュールの要素にアクセスするには
「dc_要素名」というアクセサが用意されています。全ての要素の
配列にアクセスするには「dc_要素の複数形」とします．
(rights の場合は dc_rightses とする必要があります)

複数形でアクセスした場合は「要素の内容を表す文字列」ではなく，
「要素を表すオブジェクト」の配列が返ります．「要素を表すオブ
ジェクト」から「要素の内容を表す文字列」を取得するには
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はファイルに保存されていて
引数で与えられるものとします。

  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
