2009年10月24日土曜日

ActionScriptでAtom/RSSを扱う

作成している空うさぎで、RSSの読み込みを対応するため、Atom/RSSのフィード解析を作っていました。

はじめは、as3syndicationlibというのを使ってみました。
Atom,RSS1.0,RSS2.0を判断し、扱いやすいオブジェクトに変換してくれるものです。
ですが、Gmailのフィードが解析ができない、Redmineの更新日付がとれない...などの現象がみえたので、自分で作ってみました。
はじめは、自分で作るなんて面倒だしな〜と二の足を踏んでいたのですが、いざ作ってみると簡単に作れるもんですね。

まずは、Atom, RSS1.0, RSS2.0の判断ですが、XMLに記述されている名前空間で判断します。

<feed xmlns="http://www.w3.org/2005/Atom">

上記の名前空間は、ActionScriptのXMLでは、namespace()という所に格納されているのでそれを使います。

public function parseFeed(xml:XML):void {

if (xml.namespace().uri.toLowerCase() == "http://www.w3.org/2005/atom"
|| xml.namespace().uri.toLowerCase() == "http://purl.org/atom/ns#") {
trace("atom");
return;
}

var namespaces:Array = xml.namespaceDeclarations();
for (var i:uint = 0; i < namespaces.length; ++i) {
if (namespaces[i].uri.toLowerCase() == "http://purl.org/rss/1.0/") {
trace("This is RSS 1.0");
return;
}
}
}

if (xml.name() == "rss" && Number(xml.@version) <= 2) {
trace("This is RSS 2.0 or 0.9.*");
return;
}
}

こんな感じ。

次にフィードの種類毎で値を取得していきます。
例えばTwitter検索では、以下のようなAtomのフィードが取得できます。

<feed aaa:lang="en-US" xmlns:google="http://base.google.com/ns/1.0" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns="http://www.w3.org/2005/Atom" xmlns:twitter="http://api.twitter.com/" xmlns:aaa="http://www.w3.org/XML/1998/namespace">
..(省略)..
<entry>
<id>tag:search.twitter.com,2005:4967308299</id>
<published>2009-10-18T14:56:45Z</published>
<link type="text/html" href="http://twitter.com/aqubi/statuses/4967308299" rel="alternate"/>
<title>今はRSSフィードの読み込みを実装中 #sorausagi</title>
<content type="html">今はRSSフィードの読み込みを実装中 <a href="http://search.twitter.com/search?q=%23sorausagi"><b>#sorausagi</b></a></content>
<updated>2009-10-18T14:56:45Z</updated>
<link type="image/png" href="http://a3.twimg.com/profile_images/60942919/usa200_normal.png" rel="image"/>
<twitter:source><a href="http://apiwiki.twitter.com/" rel="nofollow">API</a></twitter:source>
<twitter:lang>ja</twitter:lang>
<author>
<name>aqubi (ogawa hideko)</name>
<uri>http://twitter.com/aqubi</uri>
</author>
</entry>
...(省略)...
</feed>


feed/entry にエントリがあるので、xml.entry と取ってきたいところですが、namespaceが指定されているのでその指定が必要になってきます。

public static const ATOM:Namespace = new Namespace("http://www.w3.org/2005/Atom");

public function parseAtomFeed(xml:XML):void {
var list:XMLList = xml.ATOM::entry;
for each(var item:XML in list){
trace("id=" + item.ATOM::id);
trace("title=" + item.ATOM::title);
}
}

ちょっと面倒ですけどねー。

エントリに含まれる日付ですが、
Atomの場合だと、2009-10-09T12:42:06Z というフォーマット。
Rssの場合だと、Wed, 14 Oct 2009 18:32:33 GMT というフォーマットが入ってきます。
この解析は as3corelib の中の com.adobe.utils.DateUtils を使って解析できるようです。
Atomの場合は、DateUtils.parseW3CDTF , RSSの場合は、DateUtils.parseRFC822 を使います。

これらの方法を使って、それなりに解析できるようになったんですが、やっぱイメージが欲しくなる。
Twitter検索の場合は、<link type="image/png" で、ユーザのイメージURLが取得できるんですが、こうやって指定してくれているフィードは少ない気がする。
ぜひフィードプロバイダはこぅいぅイメージのURL情報を提供していく方向にしてもらいたいw
• • •