いまさらながら、Google AJAX Feed APIを触っているのですが、「dc:date」みたいな名前空間プリフィックス(接頭辞)が付いてる要素が拾えなくて困りました。それをどう解決したか、という話。検索しても意外と見つからない。まあ、名前空間とかプリフィックスっていうのも今回初めて理解したわけですが。たどり着くまでの話が長いので注意。
Google AJAX Feed APIってのはクロスドメインでの利用を可能にするライブラリというかなんというか。今、Googleのサイトを見たら現在の名称はGoogle Feed APIになってるのかな? ということで、公式はここか。
Getting Started – Google Feed API — Google Developers
まず、Google AJAX Feed APIを触るにあたって最初に参考したのはこれ。
RSSなどのxmlファイルを静的なHTMLに表示させる方法あれこれ(2012.9.4追記) | くろひつじのメモ帳
最初のサンプルが動いてちょっと感動。しかし、最初に書いたような「dc:date」みたいな、コロン(「:」)で区切られた要素にはアクセスできないっぽい。試してみたところ、例にある「entry.title」みたいに「entry.dc:date」とやってみてもダメなのだった。
フィードの種類はRSSとかAtomとかいろいろあって、日付が入ってる要素がそれぞれ違うという。「dc:date」(RSS 1.0?)だったり「pubDate」(RSS 2.0?)だったり、「published」(Atom?)だったりといった具合のようだ(このへんちょっと理解があやしい)。で、今回対象としたのが、RSS 1.0だったので、こういう事態に陥ったという感じ。まあ、これに限らずコロンで区切られた要素名ってのはほかでもいっぱいあるので、これをクリアしないとこの先に進めないとい思ったり。
jQueryを使った例が上記には掲載されているのだけど、今回はそれを使わないでやりたいというのがあった。自分のサイトだけならいいのだけど、今後は他の人にも使ってもらうということも想定。その際に、jQueryのコンフリクトとか考えるとまたいろいろ面倒なことになりそうだったので。
で、さらに探すとこんなのも発見。同じようなことで悩んでいる。
google ajax feed api | JavaScriptのQ&A【OKWave】
dc:dateの表示がわからない – webarton blog
その後いろいろ探すと、うまくいったという話はあるものの、実際に試してみるとIEだけダメ。うーむ。シェアが一番高いブラウザで動かなくてもいいというわけにはいかないのだ。
また、えんえん検索。やっとヒントになりそうなものに行き当たる。
Google AJAX Feed API – IT-Walker on hatena
フォーマット定数の部分だ。以下、引用。
google.feeds.Feed.MIXED_FORMAT … JSONオブジェクト + XML形式。結果オブジェクトとフィードエントリに「xmlNode」というプロパティが加わり、前者の場合はフィード全体を、後者の場合は各エントリを表すXMLノードが格納される。この形式が必要なのは、フィードに含まれる、名前空間の異なる拡張にアクセスするときなど。
「名前空間の異なる拡張にアクセスするとき」っていうのがポイントか。というわけで、Googleにあったサンプルで「google.feeds.Feed.MIXED_FORMAT」ってのがあるやつを見ると、なんとなく見えてきた。ほうほう、こういうことか。と、ここまでいろいろ調べてみて、再度これまでチェックしたページ(上記リンク以外にもたくさん)を見ると、いくつかヒントがあったり、ほぼ正解が書いてあるところもあったり。理解が足りないと、正解にも気付けないということを知ることになったり。
日付を表示するサンプル
というわけで、長い前フリ終わり。以下が今回たどりついたコード。まだ理解が足りない状態なので、間違っているところも当然あるわけですが、とりあえず動いてはいます。では、どうぞ。
リスト1. Google Ajax Feed APIの読み込み
まずは、Googleから読み込み。以前はキーの取得が必要だったみたいですが、今は不要だそうです。
<script src="http://www.google.com/jsapi" type="text/javascript"></script>
リスト2. スクリプト本体
次、作ったスクリプト本体。というか、最初のリンクのスクリプトにいろいろ足したやつ。APIで取得したデータの表示方法とかですね。
<script type="text/javascript"> function printFeed(option){ var xmlUrl = option.xmlUrl || ""; //feedのURL var setNum = option.setNum || 10; //表示件数 var setID = option.setID || "targetID"; //表示先のID google.load("feeds", "1"); function initialize() { var html = ''; var feed = new google.feeds.Feed(xmlUrl); feed.setNumEntries(setNum); feed.setResultFormat(google.feeds.Feed.MIXED_FORMAT); //出力フォーマット指定 feed.load(function(result) { if (!result.error){ var container = document.getElementById(setID); for (var i = 0; i < result.feed.entries.length; i++) { var entry = result.feed.entries[i]; entry.dc= dc; //メソッド追加 var title = entry.title; //記事タイトル取得 title = title.replace(/"/g, """); //記事タイトルの引用符"を"に var link = entry.link; //記事のリンクを取得 var date = entry.pubDate || entry.published || entry.dc("date"); //記事の日付を取得 //表示する部分を整形 html += '<div class="itsrank-each">'; html += '<a href="' + link + '" target="_blank">' + title +'</a>'; html += ' (' + date + ')'; html += '</div>'; } container.innerHTML = '<div class="feed">' + html + '</div>'; } }); } google.setOnLoadCallback(initialize); //メソッドの定義 function dc(name){ var checkNodes = google.feeds.getElementsByTagNameNS( this.xmlNode,"http://purl.org/dc/elements/1.1/", name); var result = []; if (checkNodes) { for (var cn=0; cn < checkNodes.length; cn++) { var cnode = checkNodes[cn]; result[cn] = cnode.firstChild.nodeValue; } } return result[0]; } } </script>
ポイントだと思われるのは、は11行目の出力フォーマット指定。あと、名前空間が異なる要素を取得するための関数を「dc」という名前で作成(34行目から)し、entryにメソッドとして追加(17行目)してるところとか。
これにより、「dc:xxx」っていう要素にアクセスしたいときは、「entry.dc(“xxx”)」とすればいいようになりました。オブジェクト志向がまだ理解できてないので、もっとスマートな方法もあるような気もするんですが。
21行目は、各種フィードに対応するためのもの。pubDateがなければpublished、それもなければentry.dc(“date”)を見るっていう感じです。これも無駄が多そうですが、ifとかcaseよりは楽だったので。
あと、重要なところ忘れてた。36~37行目。「google.feeds.getElementsByTagNameNS」は「getElementsByTagNameNS」のGoogleによるクロスブラウザなやつだそうだ。どこで読んだか忘れたけど。これでIEでもちゃんと動くみたいです。
それから3~5行目あたりは、このスクリプトを使いまわして複数のフィードを別々のカタチで表示したいときのための仕組み。表示設定などを別にできるようにしてます(ついでに指定がない場合の初期値なども定義)。このリスト2を外部ファイル化して、フィードのURLや件数を別に指定して表示させられるようにということで。
リスト3. 表示する先と表示設定をするスクリプト
最後は、表示先となる部分と、フィードのURLと表示件数、表示先を設定するスクリプト。
◆index.rdf<br /> <div id="feed-rdf">Loading..... (ここに表示される予定)</div> <script type="text/javascript"> printFeed({ "setID" : "feed-rdf" ,"setNum" : "2" ,"xmlUrl" : "http://pointofviewpoint.air-nifty.com/blog/index.rdf " }); </script> ◆atom.xml<br /> <div id="feed-atom">Loading..... (ここに表示される予定)</div> <script type="text/javascript"> printFeed({ "setID" : "feed-atom" ,"setNum" : "2" ,"xmlUrl" : "http://pointofviewpoint.air-nifty.com/blog/atom.xml " }); </script> ◆rss.xml<br /> <div id="feed-rss">Loading..... (ここに表示される予定)</div> <script type="text/javascript"> printFeed({ "setID" : "feed-rss" ,"setNum" : "2" ,"xmlUrl" : "http://pointofviewpoint.air-nifty.com/blog/rss.xml " }); </script>
出力先となる要素(以下ではdivタグ)のidと、スクリプトのsetIDが対になるようにします。複数のフィードを別の場所に表示するなんてことも可能になります。もちろん、その場合も、リスト1とリスト2は1つだけあればOKです。どうですかね?
以上がリストです。
で、これを実行した結果が下になります。このブログが配信しているフィードは3種類あるのですが、それを全部出力しています。
出力サンプル
◆index.rdf
◆atom.xml
◆rss.xml
で、日付の形式が違う!と気づく方もいらっしゃるかもしれません。フィードにより形式が違うそうです。日付のフォーマットをJavaScriptのDate()で整形する方法もあるそうなんですが、IEだとうまくいかないとかいろいろあるみたいですよ。これもかなり調べたのですが、けっこうややこしいし、今回はそこまでは踏み込まないことにします。また、まとまったら書いてみたりするかもしれません。
ということで、勉強したことメモでした。
上記のほか、参考にしたのはこのへん。
コメント