越前屋、お主も悪よのう

WEB屋の日常。

*

jFeed : jQueryプラグインでRSSやATOMを読み込み・解析・出力

      2011/01/21

jQueryでRSSやATOMを簡単に扱えるプラグイン、jFeed。
それ自体は簡単なんですが、周辺で色々と問題があったので記しておきます。

jQuery: The Write Less, Do More, JavaScript Library
http://jquery.com/

jFeed: JavaScript jQuery RSS/ATOM feed parser plugin – jf-hovinne.blog
http://www.hovinne.com/blog/index.php/2007/07/15/132-jfeed-jquery-rss-atom-feed-parser-plugin

0.jFeedの設定・使用方法

a.headにパスを通す。

<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="jquery.jfeed.js"></script>

b.JSを用意、下記ソースではページ読込終了後にアラートがでます。

$(document).ready(function(){
  jQuery.getFeed({
    url: 'rss.xml',
    success: function(feed) {
      alert(feed.title);
    }
 });
});

c.プロパティはこんな感じ

JFeed properties:
  feed.type
  feed.version
  feed.title
  feed.link
  feed.description
  feed.language
  feed.updated
  feed.items: an array of JFeedItem

JFeedItem properties:
  item[n].title
  item[n].link
  item[n].description
  item[n].updated
  item[n].id

1.大前提としてJavaScriptでは外部サイトのXML(RSSやATOMもXML形式の一つ)にアクセスできません。
いきなり目の前が真っ暗になりますね、だいたいRSSなんて外部のものを読み込んで、どうにかしたいのがほとんどですから。
そんな時のためにjFeedではproxy.phpが用意されていますので、proxy.php?url=外部RSSのURL等と指定すればproxy.phpが外部RSSをそのまま出力してくれますので解決。
問題はPHPが使えない時、某サイトでは同じプログラムをaspxとかで(拡張子が違うだけで、実はphpかもしれません)作ってました。プログラムが動かせない場合は、きっぱり諦めてJSONでパブリッシュしてもらうなど、他の方法を考えましょう、時間の無駄です。

2.Internet Explolerではproxy.phpを介さないで、直にXMLを指定してもXMLとして読み込まれない。(ローカル、あるいはサーバの設定によって)
IEではXMLをtext/xmlではなくプレーンテキストとして受信するようです。proxy.phpを間に入れれば解決するのですが、直にXMLを叩きたい場合は以下を参考にしてください。

Specifying the Data Type for AJAX Requests – jQuery JavaScript Library
http://docs.jquery.com/Specifying_the_Data_Type_for_AJAX_Requests

iFeedに上記を埋め込む場合は

a.iFeedはミニマム化されていない jquery.jfeed.js を読込み、これを修正します。
#わかる人は分割されているsrcでもOK←そんな人はこのエントリを読んでないと思いますが。

<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="jquery.jfeed.js"></script>

or

<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="jfeed.js"></script>
<script type="text/javascript" src="jfeeditem.js"></script>
<script type="text/javascript" src="jrss.js"></script>

b.jfeed.jsの$.ajaxを以下のように書き換えます。

$.ajax({
  type: 'GET',
  url: options.url,
  data: options.data,
  dataType: 'xml',
  success: function(xml) {
    var feed = new JFeed(xml);
    if(jQuery.isFunction(options.success)) options.success(feed);
  }
});

$.ajax({
  type: 'GET',
  url: options.url,
  data: options.data,
  dataType: ($.browser.msie) ? "text" : "xml",
  success: function(data) {
    var xml;
    if (typeof data == "string") {
      xml = new ActiveXObject("Microsoft.XMLDOM");
      xml.async = false;
      xml.loadXML(data);
    } else {
      xml = data;
    }
    var feed = new JFeed(xml);
    if(jQuery.isFunction(options.success)) options.success(feed);
  }
});

3.FireFoxだとXMLの相対指定../がうまくいかない
webサーバにあげれば大丈夫なので目をつぶります。

4.categoryとかもパースさせたい
2.の手順でソースを読み込み、各JSの該当箇所を追記します。

jFeed pluginで遊んでみた
http://www.markdiary.com/archives/2010/03-28075555.php

<category>と、<headline url=””>を追加したい場合、jquery.jfeed.js の下記を変更します。(文末の,の有無に注意!)

jQuery.getFeed = function(options) {

    options = jQuery.extend({
    
        url: null,
        data: null,
        success: null
        
    }, options);

    if(options.url) {

        $.ajax({
            type: 'GET',
            url: options.url,
            data: options.data,
            dataType: 'xml',
            success: function(xml) {
                var feed = new JFeed(xml);
                if(jQuery.isFunction(options.success)) options.success(feed);
            }
        });
    }
};

function JFeed(xml) {
    if(xml) this.parse(xml);
};

JFeed.prototype = {

    type: '',
    version: '',
    title: '',
    link: '',
    description: '',
    parse: function(xml) {
        
        if(jQuery('channel', xml).length == 1) {
        
            this.type = 'rss';
            var feedClass = new JRss(xml);

        } else if(jQuery('feed', xml).length == 1) {
        
            this.type = 'atom';
            var feedClass = new JAtom(xml);
        }
        
        if(feedClass) jQuery.extend(this, feedClass);
    }
};

function JFeedItem() {};

JFeedItem.prototype = {

    title: '',
    link: '',
    description: '',
    updated: '',
    id: '',
    category: '',
    headline_url: ''
};

function JAtom(xml) {
    this._parse(xml);
};

JAtom.prototype = {
    
    _parse: function(xml) {
    
        var channel = jQuery('feed', xml).eq(0);

        this.version = '1.0';
        this.title = jQuery(channel).find('title:first').text();
        this.link = jQuery(channel).find('link:first').attr('href');
        this.description = jQuery(channel).find('subtitle:first').text();
        this.language = jQuery(channel).attr('xml:lang');
        this.updated = jQuery(channel).find('updated:first').text();
        
        this.items = new Array();
        
        var feed = this;
        
        jQuery('entry', xml).each( function() {
        
            var item = new JFeedItem();
            
            item.title = jQuery(this).find('title').eq(0).text();
            item.link = jQuery(this).find('link').eq(0).attr('href');
            item.description = jQuery(this).find('content').eq(0).text();
            item.updated = jQuery(this).find('updated').eq(0).text();
            item.id = jQuery(this).find('id').eq(0).text();
            item.category = jQuery(this).find('category').eq(0).text();
          item.headline_url = jQuery(this).find('headline').eq(0).attr('url');
            
            feed.items.push(item);
        });
    }
};

function JRss(xml) {
    this._parse(xml);
};

JRss.prototype  = {
    
    _parse: function(xml) {
    
        if(jQuery('rss', xml).length == 0) this.version = '1.0';
        else this.version = jQuery('rss', xml).eq(0).attr('version');

        var channel = jQuery('channel', xml).eq(0);
    
        this.title = jQuery(channel).find('title:first').text();
        this.link = jQuery(channel).find('link:first').text();
        this.description = jQuery(channel).find('description:first').text();
        this.language = jQuery(channel).find('language:first').text();
        this.updated = jQuery(channel).find('lastBuildDate:first').text();
    
        this.items = new Array();
        
        var feed = this;
        
        jQuery('item', xml).each( function() {
        
            var item = new JFeedItem();
            
            item.title = jQuery(this).find('title').eq(0).text();
            item.link = jQuery(this).find('link').eq(0).text();
            item.description = jQuery(this).find('description').eq(0).text();
            item.updated = jQuery(this).find('pubDate').eq(0).text();
            item.id = jQuery(this).find('guid').eq(0).text();
            item.category = jQuery(this).find('category').eq(0).text();
          item.headline_url = jQuery(this).find('headline').eq(0).attr('url');
            
            feed.items.push(item);
        });
    }
};

ここまで

 - jQuery