もっと便利に!jQueryでラクラクサイト制作(実践サンプル付き)

第18回jQueryでAJAX入門:RSSをAJAXで取得してリストに表示する

他ページなどのコンテンツを動的に表示するAJAXもjQueryを使えば驚くほど簡単に利用することができます。今回はAJAXを利用して、RSSフィードを取得、表示してみましょう。

RSS

普段の情報収集でRSSリーダーを使っている方は多いと思いますが、RSSフィードと言っても、現在使われているものは、主なものでRSS1.0、RSS2.0というようにバージョンが2つあり、これらはXMLの形式が多少違いますので、分かりやすいように今回はRSS2.0に対象を絞ります。他にもAtomという規格自体が違うフィードもあります。

XML?

画像

RSSはXML(Extensible Markup Language)という言語で書かれています。以下はgihyo.jpのRSS2.0のフィードです。リンク先を開いてブラウザの「ページのソース」などで、ソースを確認してみてください。

また、以下は5509のRSS2.0のフィードを一部抜粋したものです。

RSSサンプルソース
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
    xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:wfw="http://wellformedweb.org/CommentAPI/"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:atom="http://www.w3.org/2005/Atom"
    xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
    xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
>
<channel>
    <title>5509(+1)</title>
    <atom:link href="http://moto-mono.net/feed" rel="self" type="application/rss+xml" />
    <link>http://moto-mono.net</link>
    <description>Output the knowledge</description>
    <lastBuildDate>Sun, 28 Feb 2010 05:18:47 +0000</lastBuildDate>
    <generator>http://wordpress.org/?v=2.8.1</generator>
    <language>ja</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
        <title>コーダー向け勉強会「.coder」の開催が決定しました</title>
        <link>http://moto-mono.net/2010/02/22/dotcoder_session1.html</link>
        <comments>http://moto-mono.net/2010/02/22/dotcoder_session1.html#comments</comments>
        <pubDate>Mon, 22 Feb 2010 10:24:34 +0000</pubDate>
        <dc:creator>nori</dc:creator>
        <category><![CDATA[WebDev]]></category>
        <guid isPermaLink="false">http://moto-mono.net/?p=2205</guid>
        <description><![CDATA[内容]]></content:encoded>
        <wfw:commentRss>http://moto-mono.net/2010/02/22/dotcoder_session1.html/feed</wfw:commentRss>
        <slash:comments>0</slash:comments>
    </item>
</channel>
</rss>

XMLもjQueryで要素を取得できる

XHTMLはXML互換を目指したHTMLですが、本来のXMLはソースを見れば分かる通り、HTMLとは少し印象が違います。ただ、タグで囲われていたりして、実はXMLもHTMLと同じようにDOM構造を持っています。

例えば記事は、各item要素に該当します。また、記事のURLはlink要素に、タイトルはtitle要素にそれぞれ入っていますね。

何がいいたいかと言うと、XMLもHTMLと同じようにjQueryで要素を取得できるということです。一番シンプルにlink要素のURLを抜き出したい場合は、以下のようにします。

要素の取得
var URL = $('link','item').text();

HTML要素の取得とまったく同じですね。この事は今回とても重要なことなので、覚えておいてください。

jQueryでAJAX

AJAX(Asynchronous JavaScript + XML)はその名前の通り、本来はJavaScriptとXMLでページの遷移なく、データを受信してページの情報を書き換える、というものです。一般的には非同期通信と言われます。

最近ではAJAXのWebアプリもかなり多いので、目にすることも多いと思います。

AJAXの制約

AJAXは一見便利なようですが、通信にはクロスドメイン(ドメインをまたぐ)上の制約があります。制約というのは、他のドメインのサイトのデータは取得できない、という点です。この問題は、システム側で一度キャッシュをして渡す、であるとか、Google AJAX Feed APIを利用する、取得するデータにXMLではなくJSONPを使う、など様々な方法で回避できるのですが、今回はそれらは行わずシンプルにローカルにXMLを保存したものを使うことにします。

$.ajax()メソッド

今回AJAX通信を実現するにあたり、jQueryの.ajax()メソッドを利用します。.ajax()は以下のように値を渡すことで利用できます。

$.ajax({
    dataType: 'xml',
    url: 'feed/rss2.xml',
    success: function(data) {
        // 引数で受け取るdataがRSSになる
        // ここに実行したい処理を書く
    }
});

RSSをリストに表示する

ようやく本題ですが、実は今回やることはとても単純です。

仕様は以下の通りです。

  1. div#rssの中にul要素を入れる
  2. RSSフィードを取得
  3. div#rss>ulにフィードから取得したタイトルリンクを追加
  4. 3を繰り返す

AJAX自体は先に述べた、.ajax()で特に何も気にせずできてしまうので、気にせずに実際にコードを書いてみましょう。

AJAXでRSSフィードを表示する
jQuery(function($){
    // ul要素を入れておく
    var rssBlock = $('#rss').append('<ul/>');
    // RSSの取得
    $.ajax({
        // 読み込むデータはXML
        dataType: 'xml',
        // 読み込みデータのURL
        url: 'feed/rss2.xml',
        // Ajaxの通信が成功した場合
        success: function(data) {
            
            // RSSにitem要素がひとつもなかった場合
            if( $('item', data).length<1 ) {
                $('ul', rssBlock).append('<li>記事がありません。</li>');
                return false;
            }
            
            // item毎に・・・
            $('item', data).each(function() {
                
                // itemの中のlinkとtitleを抜き出してulに追加する
                var item = $(this);
                $('ul', rssBlock).append(
                    $('<li/>').append(
                        $('<a/>', {
                            href: $('link', item).text(),
                            text: $('title', item).text()
                        })
                    )
                );
            });
        }
    });
});

コード自体はとてもシンプルで単純です。ポイントは2つあり、まずはsuccess: function(data){ で受け取っているdataです。

success: function(data){
	// ここではdataはRSSを意味する
}

コメントの通り、dataはRSSそのものなので、次のポイントである最後らへんの

$('link', item).text()
$('title', item).text()

で、HTMLと同じようにjQueryでリンク先とタイトルを抜き出すことができます。

実行結果を見てみましょう。

今回のコードで、1カ所見覚えがない書き方があるのですが、分かりますか?

答えは以下の部分です。

$('<a/>', {
    href: $('link', item).text(),
    text: $('title', item).text()
})

ここは今まであれば、以下のように.attr()と.text()2つに分けてメソッドチェーンで書いていました。

$('<a/>')
    .attr('href',$('link', item).text();
    .text($('title', item).text());

これがjQuery1.4以降は最初のパターンのように、$()の第2引数にまとめて書くことができます。何気にとても便利でコードが見やすくなるので、1.4以降を使っている方は覚えておくといいでしょう。

プラグイン化

RSS2.0をリストで表示する、という機能は実装できたので、色々な場面で使えるようにプラグインにしてみましょう。まずは完成したソースコードを見てください。

RSS2Render
(function($){

    // Extend the jQuery fn namespace
    $.fn.extend({
        // RSS2Render
        rss2render: function(options) {
            // 今回使う変数たち
            var self = $(this),
                c = $.extend({
                    url: null,
                    number: 10
                }, options || {});

            // URLがなければ処理を終了する
            if( !c.url ) {
                return false;
            }

            // loading文字列とRSSを一覧で表示するためのul要素を入れておく
            self.append(
                '<div id="loading">loading...</div>',
                '<ul/>'
            );
            
            // RSSの取得
            $.ajax({
                // 読み込むデータはXML
                dataType: 'xml',
                // 読み込みデータのURL
                url: c.url,
                // Ajaxの通信が成功した場合
                success: function(data) {
                    // loading文字列を消去
                    $('#loading', self).remove();
                    
                    // RSSにitem要素がひとつもなかった場合
                    if( $('item', data).length<1 ) {
                        $('ul', self).append('<li>記事がありません。</li>');
                        return false;
                    }
                    
                    // item毎に・・・
                    $('item', data).each(function(i) {
                        // 指定した数を超えた場合は終了する
                        if( i > (c.number - 1) ) {
                            return false;
                        }
                        
                        // itemの中のlinkとtitleを抜き出してulに追加する
                        var item = $(this);
                        $('ul', self).append(
                            $('<li/>').append(
                                $('<a/>', {
                                    href: $('link', item).text(),
                                    text: $('title', item).text()
                                })
                            )
                        );
                    });
                }
            });
        }
    });

})(jQuery);

実行する場合は以下のように実行します。

jQuery(function($){
    
    $('#rss').rss2render({
        url: 'feed/rss2.xml',
        number: 5
    });

});

変更点

プラグインにした際の変更点は

  • URLや表示件数はrss2renderのオプションで指定できる
  • 読み込みが完了するまでloadingテキストを表示

の2点です。

プラグインの定義方法

また今回はプラグインの定義方法をいつもとは違う方法にしてみました。

いつもの方法
$.fn.rss2render = function() {
        // 処理
}
今回の方法
$.fn.extend({
        rss2render: function() {
                // 処理
        }
});

上記の2つは書き方が違うだけで、他には違いはありません。使っているプラグインによっては、後者の書き方で書いているプラグインもあるので、これらは同じ意味だよ、ということを理解してもらえればと思います。

オプション

実行するときに

jQuery(function($){
    
    $('#rss').rss2render({
        url: 'feed/rss2.xml',
        number: 5
    });

});

のように、rss2renderの引数に{}でオプションを渡していますが、jQueryプラグインを使ったことのある方にはお馴染みの方法ですね。必要なものだけ渡すことができるので、いくつも引数を書く必要がなく、とても便利です。

オプションの定義方法もとても簡単で、以下のようにします。

var c = $.extend({
    url: null,
    number: 10
}, options || {});

変数cがオプションで、オプションのプロパティとして、値を持たせます。左が名前で、右がデフォルトの値になります。

ただし、このスクリプトの場合、URLがないと何もできないので、以下の処理を追加しておきます。

// URLがなければ処理を終了する
if( !c.url ) {
    return false;
}

loading中はテキストを表示する

まず初期化のタイミングで以下のように<div id="loading">loading...</div>を入れておきます。

// loading文字列とRSSを一覧で表示するためのul要素を入れておく
self.append(
        '<div id="loading">loading...</div>',
        '<ul/>'
);

$.ajax()が成功したら、.remove()で削除します。

success: function(data) {
        // loading文字列を消去
        $('#loading', self).remove();

オプションで指定した数を超えた場合終了する

さらに、この処理を追加するために、.each()の引数にiを渡しておきます。

$('item', data).each(function(i) {
        // 処理が繰り返される毎に i は ++ され 1ずつ増えていく
});

このiを利用して、c.number - 1 よりも i が大きくなったら処理をやめるようにします。

$('item', data).each(function(i) {
        // 指定した数を超えた場合は終了する
        if( i > (c.number - 1) ) {
                return false;
        }
        
});

以上でプラグイン化まで出来ました。完成サンプルを確認してみてください。表示件数は5件にしています。

おすすめ記事

記事・ニュース一覧