Do You PHP?    
Search Engine Optimization  php5 powerd  Valid XHTML 1.0!  Valid CSS!  このサイトのはてなブックマーク数 



last updated
2004/01/13

counter hits
since 1999/11/06


XMLパーサ(SAX)でRSSしてみる

alertここにある情報はかなり古くなっており、正しくなくなっている可能性があります。掲載しているサンプルコードiなどは、最新のPHPでは動作しない、もしくは、別途設定・調整が必要になるかも知れません。情報を鵜呑みにせず、あなたの手を動かして、あなたの目で確認してください。

最近では以前ほど「XMLブーム」が感じられなくなりましたが、ひょっとするとこのRSSで再発火(?)するかも知れない、と思ってたりします。

memoPEARにもXML_RSSクラスが用意されているようで、SAXタイプのようです。XML_RSSの方がコードが非常にすっきり書けます。

RSS(RDF Site Summary)とは、XML関連使用の1つで、これを利用することにより「共通の書式でドキュメントの見出し、要約などのリストを提供することで、サイトの更新情報などを効率的に公開できる(The Web KANZAKIより引用)」ようになります。

最新の仕様はRSS1.0で、日本語の解説ページでは以下のページが参考になります。

上記のページにもありますが、RSSを配布しているサイトはW3Cを初め、日本のサイトでもかなりの数があります。PHP本家も2002/12/01付けでRSSが利用可能となりました。

今回はPHP本家スラッシュドットジャパンのRSSを対象に、XMLパーサ関数(SAX)を使ってニュース一覧のリンクを作成するサンプルを作ってみました。PHPマニュアルにあるサンプルをベースとしていますが、RSS中のitem要素毎にItemオブジェクトを作成し、

  • title要素
  • link要素
  • discription要素

の内容をセットしています。最終的な結果は、グローバル変数である「$items」をループさせて取り出し、リンクとして表示します。

●rss.php

<?php
/**
 * 各TOPIC(itemノード)を格納するクラス
 */
class Item
{
    var $data_;
    var $mode_;
    function setMode($mode)
    {
        $this->mode_ = $mode;
        if (!isset($this->data_[$mode])) { $this->data_[$mode] = ""; }
    }
    function getMode() { return $this->mode_; }
    function put($str) { $this->data_[$this->mode_] = $str; }
    function get() { return $this->data_; }
}
?>
<?php
/**
 * 最終的なTOPICの配列。それぞれの要素は、Itemオブジェクトとなる
 */
$items = array();

/**
 * 現在処理を行っているItemオブジェクト
 */
$currentItem = null;

/**
 * SAX関連の処理関数
 *
 * SAXでは、要素の開始・終了、テキストデータの処理ハンドラを
 * 作成する必要があり、引数はそれぞれサンプルの通り。
 * なお、関数名は任意で構わないが、ハンドラを設定するxml_set_xxx_handlerで
 * 間違わないように。。。
 */
function _RSSParser_startElement($parser, $name, $attrs)
{
    global $currentItem;
    if ($name == "item") {
        $currentItem = new Item();
    }
    if ($currentItem != null) {
        $currentItem->setMode($name);
    }
}
function _RSSParser_endElement($parser, $name)
{
    global $items, $currentItem;
    if ($name == "item") {
        if ($currentItem != null) {
            array_push($items, $currentItem);
            $currentItem = null;
        }
    }
}
function _RSSParser_charData($parser, $data)
{
    global $currentItem;
    $data = mb_convert_encoding($data, "euc-jp", "auto");
    if ($currentItem != null) {
        $currentItem->put($data);
        $currentItem->setMode("");
    }
}

/**
 * RSSパーサクラス
 */
class RSSParser
{
    var $xml_parser;

    function RSSParser() {
        $this->xml_parser = xml_parser_create();

        /**
         * 各ハンドラを設定する
         * 関数名は文字列で指定すること
         */
        xml_parser_set_option(
            $this->xml_parser,
            XML_OPTION_CASE_FOLDING,
            false);
        xml_set_element_handler(
            $this->xml_parser,
            "_RSSParser_startElement",
            "_RSSParser_endElement");
        xml_set_character_data_handler(
            $this->xml_parser,
            "_RSSParser_charData");
    }

    /**
     * 引数には、ファイル名かURLを指定する
     */
    function parse($file) {
        if (!($fp = fopen($file, "r"))) {
            die("could not open RDF/RSS input");
        }
        while ($data = fread($fp, 4096)) {
            if (!xml_parse($this->xml_parser, $data, feof($fp))) {
                die(sprintf("XML error: %s at line %d",
                            xml_error_string(xml_get_error_code($this->xml_parser)),
                            xml_get_current_line_number($this->xml_parser)));
            }
        }
        xml_parser_free($this->xml_parser);
    }
}
?>
<?php
/**
 * 以下、テスト用ルーチン
 */
$file = "slashdot.rdf";
//$file = "http://www.php.net/news.rss";
$test = new RSSParser();
$test->parse($file);

/**
 * 結果の表示
 */
foreach ($items as $key => $item) {
    $data = $item->get();
    printf('<li><a href="%s" title="%s">%s</a></li>', $data["link"], $data["title"], $data["title"]);
    printf('<dd>%s</dd>', $data["description"]);
}
?>

結果として、以下のようなHTMLが出力されます(適宜改行を入れています)。

●スラッシュドットジャパンの場合
<li><a href="http://slashdot.jp/article.pl?sid=02/12/04/1042219"
title="Opera Open The Web - 全てのブラウザに平等を">Opera Open The Web -
全てのブラウザに平等を</a></li>
<li><a href="http://slashdot.jp/article.pl?sid=02/12/04/0813204"
title="論文の著者は引用文献を本当に読んでいるか?">論文の著者は引用文献を本当に読んでいるか?</a></li>
<li><a href="http://slashdot.jp/article.pl?sid=02/12/04/089227"
title="日食はインターネットで">日食はインターネットで</a></li>
<li><a href="http://slashdot.jp/article.pl?sid=02/12/04/086215"
title="Mozilla 1.2.1リリース">Mozilla 1.2.1リリース</a></li>
<li><a href="http://slashdot.jp/article.pl?sid=02/12/04/057210"
title="J-OS for Palm TungstenT β版">J-OS for Palm TungstenT β版</a></li>
<li><a href="http://slashdot.jp/article.pl?sid=02/12/03/1613211"
title="MPEG-4, DivXをリアルタイム圧縮/伸張できるDSP">MPEG-4, DivXをリアルタイム圧縮/伸張できるDSP</a></li>
<li><a href="http://slashdot.jp/article.pl?sid=02/12/03/1521257"
title="青少年のネット規制に突き進む大阪府">青少年のネット規制に突き進む大阪府</a></li>
<li><a href="http://slashdot.jp/article.pl?sid=02/12/03/1152202"
title="印刷するトランジスタ">印刷するトランジスタ</a></li>
<li><a href="http://slashdot.jp/article.pl?sid=02/12/03/085207"
title="「千と千尋」DVD騒動、ついに裁判へ">「千と千尋」DVD騒動、ついに裁判へ</a></li>
<li><a href="http://slashdot.jp/article.pl?sid=02/12/03/0759219"
title="警察庁インターネット通信傍受装置の正体">警察庁インターネット通信傍受装置の正体</a></li>
  
●PHP本家の場合
<li><a href="http://www.php.net/news.rss" title="PHP news feed
available">PHP news feed available</a></li>
<dd>   The news of PHP.net is available now in RSS 1.0 format via our new
statical news.rss file. You can add this file to any news reader or portal
site to get the latest official PHP news. We strongly recommend you to cache
the contents locally on your side, as the newsfeed is updated daily. The RSS
file is available on every mirror site. </dd>
<li><a href="http://qa.php.net/" title="PHP 4.3.0RC2 Released">
PHP 4.3.0RC2 Released</a></li>
<dd>   PHP 4.3.0RC2 has been released, just in time for the Thanksgiving.
And thanks indeed must be given to those who fixed bugs and pushed this
release to be a lot closer to the final one. Please download and test it
as much as possible on real-life applications to uncover remaining issues. </dd>
<li><a href="http://www.afup.org/" title="Forum PHP 2002 in Paris,
France">Forum PHP 2002 in Paris, France</a></li>
<dd>     The French PHP User Group AFUP invites you to the </dd>
<li><a href="http://www.phpmag.de/" title="PHP Magazine - International
Edition">PHP Magazine - International Edition</a></li>
<dd>   Software </dd>
<li><a href="http://www.phparch.com/" title="New Monthly PHP Magazine
Launched">New Monthly PHP Magazine Launched</a></li>
<dd>   php|architect, a new monthly magazine dedicated exclusively to PHP,
has launched its website. php|a is published in PDF format and is available
worldwide. It covers a variety of advanced topics ranging from day-to-day
programming to the internals of PHP. A sample article on the creation of
a web-based PDF converter is also available on the magazine </dd>
<li><a href="http://qa.php.net/" title="PHP 4.3.0RC1 Released">
PHP 4.3.0RC1 Released</a></li>
<dd>   PHP 4.3.0RC1 has been released. This is the first release candidate
and should have a very low number of problems and/or bugs. Nevertheless,
please download and test it as much as possible on real-life applications
to uncover remaining issues. </dd>
                               :
  


About This Site |  Privacy Policy |  Contact
Copyright © 1999 - 2004 by Hideyuki SHIMOOKA all rights reserved.