RubyでXML(Atom 1.0)ファイルを生成したい

○何がしたいのか
RubyXML(Atom 1.0)ファイルを生成したい。
(静的なファイルを生成する。文字コードUTF-8


○まずは、RSSAtomの基本
RSS - Wikipedia
アトム - Wikipedia
http://diveintomark.org/archives/2004/05/28/howto-atom-id
RFC 4287 The Atom Syndication Format 日本語訳


Atomの生成例を想像する

<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns='http://www.w3.org/2005/Atom'>
  <title>○○ランキング!!</title>
  <subtitle>〜最強のアレランキング〜</subtitle>
  <link rel="self" type="application/atom+xml" href="http://hogehoge.jp/atom.xml"/>
  <author>
    <name>株式会社○○</name>
  </author>
  <id>tag:hogehoge.jp,2007:0</id>
  <updated>2007-12-14T05:30:02Z</updated>
  <entry>
    <title>2007年12月14日(金) ○○ランキング</title>
    <link href="http://hogehoge.jp/entry/"/>
    <published>2007-12-14T00:00:00Z</published>
    <updated>2007-12-14T05:30:02Z</updated>
    <id>tag:hogehoge.jp,2007:20071214</id>
    <category scheme='http://xmlns.com/wordnet/1.6/' term='Job'/>
    <summary>12月14日の内容・・・</summary>
  </entry>
</feed>


○上記フィードの各要素の意味

<feed>〜</feed> => http://www.futomi.com/lecture/japanese/rfc4287.html#s4_1_1
<title>〜</title> => http://www.futomi.com/lecture/japanese/rfc4287.html#s4_2_14
<subtitle>〜</subtitle> => http://www.futomi.com/lecture/japanese/rfc4287.html#s4_2_12
<link> => http://www.futomi.com/lecture/japanese/rfc4287.html#s4_2_7
<author>〜</author> => http://www.futomi.com/lecture/japanese/rfc4287.html#s4_2_1
<published>〜</published> => http://www.futomi.com/lecture/japanese/rfc4287.html#s4_2_9
<updated>〜</updated> => http://www.futomi.com/lecture/japanese/rfc4287.html#s4_2_15
<id>〜</id> => http://www.futomi.com/lecture/japanese/rfc4287.html#s4_2_6
<entry>〜</entry> => http://www.futomi.com/lecture/japanese/rfc4287.html#s4_1_2
<category>〜<category> => http://www.futomi.com/lecture/japanese/rfc4287.html#s4_2_2
<summary>〜</summary> => http://www.futomi.com/lecture/japanese/rfc4287.html#s4_2_13


RubyXML(Atom)を生成
create_xml.rb

require "rexml/document"

out_file_name = "atom.xml"
out_doc = REXML::Document.new()

#xml宣言
out_doc.add(REXML::XMLDecl.new(version="1.0", encoding="UTF-8"))
#xml_root
root_element = REXML::Element.new("feed")
root_element.add_attribute("xmlns","http://www.w3.org/2005/Atom")
out_doc.add_element(root_element)
#title
title_element = REXML::Element.new("title")
title_element.add_text("○○ランキング!!")
root_element.add_element(title_element)
#subtitle
subtitle_element = REXML::Element.new("subtitle")
subtitle_element.add_text("〜最強のアレランキング〜")
root_element.add_element(subtitle_element)
#link_self
root_element.add_element('link rel="self" type="application/atom+xml" href="http://hogehoge.jp/atom.xml"')
#author
author_element = REXML::Element.new("author")
root_element.add_element(author_element)
  #name
  name_element = REXML::Element.new("name")
  name_element.add_text("株式会社○○")
  author_element.add_element(name_element)
#id
id_element = REXML::Element.new("id")
id_element.add_text("tag:hogehoge.jp,2007:0")
root_element.add_element(id_element)
#updated
updated_element = REXML::Element.new("updated")
updated_element.add_text("2007-12-14T05:30:02Z")
root_element.add_element(updated_element)
#エントリー生成
#entry
entry_element = REXML::Element.new("entry")
root_element.add_element(entry_element)
  #entry_title
  entry_title_element = REXML::Element.new("title")
  entry_title_element.add_text("2007年12月14日(金) ○○ランキング")
  entry_element.add_element(entry_title_element)
  #link
  entry_element.add_element('link href="http://hogehoge.jp/entry/"')
  #published
  entry_published_element = REXML::Element.new("published")
  entry_published_element.add_text("2007-12-14T00:00:00Z")
  entry_element.add_element(entry_published_element)
  #updated
  entry_updated_element = REXML::Element.new("updated")
  entry_updated_element.add_text("2007-12-14T05:30:02Z")
  entry_element.add_element(entry_updated_element)
  #id
  entry_id_element = REXML::Element.new("id")
  entry_id_element.add_text("tag:hogehoge.jp,2007:20071214")
  entry_element.add_element(entry_id_element)
  #category
  entry_element.add_element("category scheme='http://xmlns.com/wordnet/1.6/' term='Job'")
  #summary
  entry_summary_element = REXML::Element.new("summary")
  entry_summary_element.add_text("12月14日の内容・・・")
  entry_element.add_element(entry_summary_element)

File.open(out_file_name,"w") do |outfile|
  out_doc.write(outfile, 0)
end

※通常は、entry生成の部分は生成したい分だけル―プします。
上記を実行すると、Rubyファイルと同じ階層にatom.xmlができます。


○フィードのチェック
http://feedvalidator.org/ がよいかもUTF-8対応してるし。


○はまりポイント

<link rel="self" type="application/atom+xml" href="http://hogehoge.jp/atom.xml"/>

↑はxmlファイル自身のURLを記載する。


○参考
XMLを静的なファイルとして出力
http://www6.airnet.ne.jp/manyo/xml/ruby/step7.html
http://www6.airnet.ne.jp/manyo/xml/ruby/step8.html
XMLをブラウザで(動的に)出力
RailsでXMLを生成&出力(RSS出力サンプル): Rails開発日記
http://www.stbbs.net/blog/2007/09/railsrxml-xml.html
http://wota.jp/ac/?date=20050808


○おまけ・エントリー内容(summary)にHTMLタグを使いたい
http://www.atmarkit.co.jp/aig/01xml/cdata.html

・パターン1

<summary type="text/html" mode="escaped"><b>12月14日の内容・・・</b></summary>

・パターン2

<summary type="text/html">
<![CDATA[ 
<b>12月14日の内容・・・</b>
]]>
</summary>

・パターン3

<summary type="text/html">&lt;b&gt;12月14日の内容・・・&lt;/b&gt;</summary>

上記create_xml.rbの中に書いてある、.add_text←を利用するとかってにエスケープしてくれるみたいですね。

entry_summary_element.add_text("<b>12月14日の内容・・・</b>")

&lt;b&gt;12月14日の内容・・・&lt;/b&gt;

type="text/html"の指定と<>←のエスケープがポイントです。


○試した環境
Ruby 1.8.6