# Ajax RSS リーダー
Ajax を使用して RSS リーダーを構築する
Web ページ上の JavaScript コードから XML (Extensible Markup Language) を要求する記事について読んだときに最初にしようと思ったのは、RSSを取得して、それを表示することでした。しかし、私はいきなり XML HTTP (Hypertext Transfer Protocol) のセキュリティー問題に突き当たってしまいました。 のページは、 以外の場所からのページを処理できません。Web ページの中だけで汎用 RSS リーダーを構築しようという私の計画は挫折してしまいました。しかし、Web 2.0 はまさに画期的な発明であり、XMLHTTP で RSS リーダーを作成するという問題を解くことで、2.0 Web のプログラミングについて多くを学ぶことができます。
この記事では、XMLHTTP と <script> タグの両方をトランスポート・メカニズムとして使用して Ajax ベースの RSS リーダーを構築する方法を解説します。
## サーバー・サイドの構築
サーバー・サイドは、2 つの部分で構成されます。1 つはデータベースであり、もう 1 つは PHP ページのセットです。これらのページによって、フィードの追加、フィード・リストの要求、特定のフィードに関連する記事の取得ができます。まず、データベースから始めましょう。
### データベース
この記事では、MySQL データベースを使用します。リスト1 に、スキーマを示します。
##### リスト 1. データベースのスキーマ
CREATE TABLE rss_feeds ( rss_feed_id MEDIUMINT NOT NULL AUTO_INCREMENT, url TEXT NOT NULL, name TEXT NOT NULL, last_update TIMESTAMP, PRIMARY KEY ( rss_feed_id ) ); CREATE TABLE rss_articles ( rss_feed_id MEDIUMINT NOT NULL, link TEXT NOT NULL, title TEXT NOT NULL, description TEXT NOT NULL );
2 つのテーブルがあります。rss_feeds テーブルには、フィードのリストが含まれています。また、rss_articles テーブルには、各フィードに関連付けられた記事のリストが含まれています。システムが記事を更新するときには、現在の記事のうち特定の rss_feed_id に関連付けられている記事のすべてが削除されて、新しい記事のセットでテーブルが更新されます。
### データベース・ラッパー
次のステップは、アプリケーションのビジネス・ロジックを構築する PHP クラスのセットでデータベースをラップすることです。まず、リスト 2 に示されているように、DatabaseConnection シングルトンから始めます。これは、データベースへの接続を管理します。
##### リスト2. rss_db.php の DatabaseConnection シングルトン
<?php // Install the DB module using 'pear install DB' require_once 'DB.php'; require_once 'XML/RSS.php'; class DatabaseConnection { public static function get() { static $db = null; if ( $db == null ) $db = new DatabaseConnection(); return $db; } private $_handle = null; private function __construct() { $dsn = 'mysql://root:password@localhost/rss'; $this->_handle =& DB::Connect( $dsn, array() ); } public function handle() { return $this->_handle; } }
これは標準的な PHP シングルトンのパターンです。データベースに接続して、handle メソッドによってハンドルを返します。このコードのもう 1 つの面白い部分は、2 つの require_once ステートメントです。最初のステートメントは、データベースに接続する PEAR (PHP Extension and Application Repository) DB モジュールを参照しています。2 つ目のステートメントは、RSS フィードを解析する XML_RSS モジュールを参照しています。正直に言うと、ここでモジュールを使用したのは、私が怠け者だからであり、さまざまな形式の RSS のすべての解析について、あれこれ心配するのがいやだったからです。これらのモジュールがインストールされていない場合は、コマンドラインに次のように入力してください。
% pear install DB
そして
% pear install XML_RSS
DB モジュールはインストールされていることが多いのですが、XML_RSS モジュールはそうではありません。
次のステップは、フィードのリストをラップするクラスを構築して、フィードの追加、フィード・リストの取得などを可能にすることです。リスト3 に、このクラスを示します。
##### リスト 3. rss_db.php の FeedList クラス
class FeedList { public static function add( $url ) { if ( FeedList::getFeedByUrl( $url ) != null ) return; $db = DatabaseConnection::get()->handle(); $rss =& new XML_RSS( $url ); $rss->parse(); $info = $rss->getChannelInfo(); $isth = $db->prepare( "INSERT INTO rss_feeds VALUES( null, ?, ?, null )" ); $db->execute( $isth, array( $url, $info['title'] ) ); $info = FeedList::getFeedByUrl( $url ); Feed::update( $info['rss_feed_id'] ); } public static function getAll( ) { $db = DatabaseConnection::get()->handle(); $res = $db->query( "SELECT * FROM rss_feeds" ); $rows = array(); while( $res->fetchInto( $row, DB_FETCHMODE_ASSOC ) ) { $rows []= $row; } return $rows; } public static function getFeedInfo( $id ) { $db = DatabaseConnection::get()->handle(); $res = $db->query( "SELECT * FROM rss_feeds WHERE rss_feed_id=?", array( $id ) ); while( $res->fetchInto( $row, DB_FETCHMODE_ASSOC ) ) { return $row; } return $null; } public static function getFeedByUrl( $url ) { $db = DatabaseConnection::get()->handle(); $res = $db->query( "SELECT * FROM rss_feeds WHERE url=?", array( $url ) ); while( $res->fetchInto( $row, DB_FETCHMODE_ASSOC ) ) { return $row; } return null; } public static function update() { $db = DatabaseConnection::get()->handle(); $usth1 = $db->prepare( "UPDATE rss_feeds SET name='' WHERE rss_feed_id=?" ); $usth2 = $db->prepare( "UPDATE rss_feeds SET name=? WHERE rss_feed_id=?" ); $res = $db->query( "SELECT rss_feed_id,name FROM rss_feeds WHERE last_update<now()-600" ); while( $res->fetchInto( $row, DB_FETCHMODE_ASSOC ) ) { Feed::update( $row['rss_feed_id'] ); $db->execute( $usth1, array( $row['rss_feed_id'] ) ); $db->execute( $usth2, array( $row['name'], $row['rss_feed_id'] ) ); } } }
add メソッドは、フィードをリストに追加して、フィードを更新します。getAll メソッドは、すべてのフィードのリストを返します。getFeedInfo メソッドは、特定のフィードに関する情報を返します。getFeedByUrl メソッドは getFeedInfo メソッドと同じことをしますが、フィードの URL をキーとして使用します。また、update 関数は、特定のフィードが最近 10 分以内に更新されていなかった場合に、そのフィードに対して update メソッドを呼び出します。
リスト4 に、ビジネス・ロジック・クラスの最後のクラスである Feed クラスを示します。このクラスには、個別のフィードを扱うメソッドがあります。
##### リスト4. rss_db.php の Feed クラス
class Feed { public static function update( $id ) { $db = DatabaseConnection::get()->handle(); $info = FeedList::getFeedInfo( $id ); $rss =& new XML_RSS( $info['url'] ); $rss->parse(); $dsth = $db->prepare( "DELETE FROM rss_articles WHERE rss_feed_id=?" ); $db->execute( $dsth, array( $id ) ); $isth = $db->prepare( "INSERT INTO rss_articles VALUES( ?, ?, ?, ? )" ); foreach ($rss->getItems() as $item) { $db->execute( $isth, array( $id, $item['link'], $item['title'], $item['description'] ) ); } } public static function get( $id ) { $db = DatabaseConnection::get()->handle(); $res = $db->query( "SELECT * FROM rss_articles WHERE rss_feed_id=?", array( $id ) ); $rows = array(); while( $res->fetchInto( $row, DB_FETCHMODE_ASSOC ) ) { $rows []= $row; } return $rows; } } ?>
Update メソッドは、RSS パーサーを使用してフィードを取得し、データベースを更新します。また、get メソッドは、特定のフィードについて、記事テーブルの現在の内容を返します。
### PHP サービス・ページ
最初に使用する必要があるページは、フィードをリストに追加する add.php ページです (リスト5)。
##### リスト 5. add.php
<?php require_once 'rss_db.php'; header( 'Content-type: text/xml' ); FeedList::add( $_GET['url'] ); ?> <done />
これは、FeedList クラスの add メソッドを包む、ごく単純なラッパーです。プロセスの成否を示すある種のXML を返す必要があり、最後の <done> タグはそのためのものです。
次のページは、list.php ページです (リスト6)。これは、データベース内のフィードのリストを返します。
##### リスト 6. list.php
<?php require_once 'rss_db.php'; $rows = FeedList::getAll(); $dom = new DomDocument(); $dom->formatOutput = true; $root = $dom->createElement( 'feeds' ); $dom->appendChild( $root ); foreach( $rows as $row ) { $an = $dom->createElement( 'feed' ); $an->setAttribute( 'id', $row['rss_feed_id'] ); $an->setAttribute( 'link', $row['url'] ); $an->setAttribute( 'name', $row['name'] ); $root->appendChild( $an ); } header( "Content-type: text/xml" ); echo $dom->saveXML(); ?>
XML を正しく簡単に書くことができるように、私は PHP コアで DOM (Document Object Model) 関数を使用して、XML DOM をその場で作成しています。次に、saveXML 関数を使用して、出力用にフォーマットします。
このページを私の Firefox® ブラウザーで見ると、図1 のような出力が表示されます。
##### 図 1. フィード・リスト XML ページ
もちろん、これは 8 つのフィードをリストに追加した後の出力です。
システムのクライアント・サイドに移る前に構築する必要がある最後のページは、read.php ページです (リスト7)。これは、特定のフィード ID に関連付けられた記事を返します。
##### リスト 7. read.php
<?php require_once 'rss_db.php'; FeedList::update(); $rows = Feed::get( $_GET['id'] ); $dom = new DomDocument(); $dom->formatOutput = true; $root = $dom->createElement( 'articles' ); $dom->appendChild( $root ); foreach( $rows as $row ) { $an = $dom->createElement( 'article' ); $an->setAttribute( 'title', $row['title'] ); $an->setAttribute( 'link', $row['link'] ); $an->appendChild( $dom->createTextNode( $row['description'] ) ); $root->appendChild( $an ); } header( "Content-type: text/xml" ); echo $dom->saveXML(); ?>
これは list.php ページと非常によく似た形式です。Feed クラスを使用して記事のリストを取得します。次に、XML DOM オブジェクトを使用して XML を作成し、出力します。このページを Firefox で見ると、図2 のような出力が表示されます。
##### 図 2. read.php ページから出力される XML
これで、サーバー・サイドは終わりです。今度は、これらの PHP ページを利用する、Ajax による DHTML (Dynamic Hyper Text Markup Language) ページを組み立てれば良い訳です。
## クライアントの構築
次にやらなければならないことは、PHP ページを使用するクライアントの構築です。手順がわかるように、3段階で構築することにします。最初のバージョン (リスト8) は、フィード・リストを示すコントロールを表示します。
##### リスト 8. index2.html
<html> <head> <title>Ajax RSS Reader</title> <style> body { font-family: arial, verdana, sans-serif; } </style> <script> var g_homeDirectory = ' var req = null; function processReqChange( handler ) { if (req.readyState == 4 && req.status == 200 && req.responseXML ) { handler( req.responseXML ); } } function loadXMLDoc( url, handler ) { if(window.XMLHttpRequest) { try { req = new XMLHttpRequest(); } catch(e) { req = false; } } else if(window.ActiveXObject) { try { req = new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) { try { req = new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) { req = false; } } } if(req) { req.onreadystatechange = function() { processReqChange( handler ); }; req.open("GET", url, true); req.send(""); } } function parseFeedList( dom ) { var elfl = document.getElementById( 'elFeedList' ); elfl.innerHTML = ''; var nl = req.responseXML.getElementsByTagName( 'feed' ); for( var i = 0; i < nl.length; i++ ) { var nli = nl.item( i ); var id = nli.getAttribute( 'id' ); var link = nli.getAttribute( 'link' ); var name = nli.getAttribute( 'name' ); var elOption = document.createElement( 'option' ); elOption.value = id; elOption.innerHTML = name; elfl.appendChild( elOption ); } } function getFeedList() { loadXMLDoc( g_homeDirectory+'list.php', parseFeedList ); } </script> </head> <body> <select id="elFeedList"> </select> <script> getFeedList(); </script> </body> </html>
このページには 1 個のコントロール、すなわち、<select> コントロールが表示されます。このコントロールには、サーバーに list.php ページを要求する getFeedList 関数によってリストが挿入されます。ページがロードされると、parseFeedList 関数が <select> コントロールに項目を追加します。
これを Firefox で見ると、図3 のような出力が表示されます。
##### 図 3. RSS リーダーの最初のバージョン
最初の数フィードをシステムに組み込むには、MySQL インターフェースを使用して、手動で追加します。
次のステップは、選択されたフィードの内容を表示することです。リスト9 に、アップグレードされたコードを示します。
##### リスト 9. index3.html
<html> <head> <title>Ajax RSS Reader</title> <style> body { font-family: arial, verdana, sans-serif; } .title { font-size: 14pt; border-bottom: 1px solid black; } .title a { text-decoration: none; } .title a:hover { text-decoration: none; } .title a:visited { text-decoration: none; } .title a:active { text-decoration: none; } .title a:link { text-decoration: none; } .description { font-size: 9pt; margin-left: 20px; } </style> <script> var g_homeDirectory = ' var req = null; function processReqChange( handler ) { ... } function loadXMLDoc( url, handler ) { ... } function parseFeed( dom ) { var ela = document.getElementById( 'elArticles' ); ela.innerHTML = ''; var elTable = document.createElement( 'table' ); var elTBody = document.createElement( 'tbody' ); elTable.appendChild( elTBody ); var nl = req.responseXML.getElementsByTagName( 'article' ); for( var i = 0; i < nl.length; i++ ) { var nli = nl.item( i ); var title = nli.getAttribute( 'title' ); var link = nli.getAttribute( 'link' ); var description = nli.firstChild.nodeValue; var elTR = document.createElement( 'tr' ); elTBody.appendChild( elTR ); var elTD = document.createElement( 'td' ); elTR.appendChild( elTD ); var elTitle = document.createElement( 'h1' ); elTitle.className = 'title'; elTD.appendChild( elTitle ); var elTitleLink = document.createElement( 'a' ); elTitleLink.href = link; elTitleLink.innerHTML = title; elTitleLink.target = '_blank'; elTitle.appendChild( elTitleLink ); var elDescription = document.createElement( 'p' ); elDescription.className = 'description'; elDescription.innerHTML = description; elTD.appendChild( elDescription ); } ela.appendChild( elTable ); } function parseFeedList( dom ) { var elfl = document.getElementById( 'elFeedList' ); elfl.innerHTML = ''; var nl = req.responseXML.getElementsByTagName( 'feed' ); var firstId = null; for( var i = 0; i < nl.length; i++ ) { var nli = nl.item( i ); var id = nli.getAttribute( 'id' ); var link = nli.getAttribute( 'link' ); var name = nli.getAttribute( 'name' ); var elOption = document.createElement( 'option' ); elOption.value = id; elOption.innerHTML = name; elfl.appendChild( elOption ); if ( firstId == null ) firstId = id; } loadFeed( firstId ); } function loadFeed( id ) { loadXMLDoc( g_homeDirectory+'read.php?id='+id, parseFeed ); } function getFeedList() { loadXMLDoc( g_homeDirectory+'list.php', parseFeedList ); } </script> </head> <body> <div style="width:600px;"> <select id="elFeedList" onchange="loadFeed( this.options[this.selectedIndex].value )"> </select> <div id="elArticles"> </div> <script> getFeedList(); </script> </div> </body> </html>
processReqChange 関数と loadXMLDoc 関数は前述のものと同じなので省略しました。コードが新しくなっているのは、 loadFeed 関数と parseFeed 関数です。これらは、read.php ページにデータを要求して、データを解析し、ページに追加します。
図4に、このページの Firefox での出力を示します。
##### 図 4. 記事リストを示すアップグレードされたページ
次のステップは、ページの仕上げとして、add.php ページによってフィードをリストに追加する機能を付け加えることです。このページの最終的なコードをリスト10 に示します。
##### リスト 10. index.html
<html> <head> <title>Ajax RSS Reader</title> <style> ... </style> <script> var g_homeDirectory = ' // The same transfer functions as before function addFeed() { var url = prompt( "Url" ); loadXMLDoc( g_homeDirectory+'add.php?url='+escape( url ), parseAddReturn ); window.setTimeout( getFeedList, 1000 ); } function loadFeed( id ) { loadXMLDoc( g_homeDirectory+'read.php?id='+id, parseFeed ); } function getFeedList() { loadXMLDoc( g_homeDirectory+'list.php', parseFeedList ); } </script> </head> <body> <div style="width:600px;"> <select id="elFeedList" onchange="loadFeed( this.options[this.selectedIndex].value )"> </select> <input type="button" onclick="addFeed()" value="Add Feed..." /> <div id="elArticles"> </div> <script> getFeedList(); </script> </div> </body> </html>
コードの大部分は同じですが、新しい「
Add Feed...」ボタンを挿入しました。このボタンをクリックすると、フィード・リストに新しい URL
を挿入するためのダイアログ・ボックスが開きます。私にとって使い勝手がよいように、ブラウザーを 2
秒間待たせて、フィードが追加されてから新しいフィード・リストを取得させています。
図5 に出来上がりのページを示します。
##### 図 5. 出来上がりのページ
かなりクールになりました。しかし、私はまだ満足してはいません。XMLHTTP セキュリティーのため、このページから JavaScript コードを取得して、他の人のブログにコピーすることができないからです。このようにできれば、誰でもフィードを見ることができます。このためには、<script> タグと JSON (JavaScript Object Notation) 構文を使用するようにサービスを作り直す必要があります。
## XML から JSON へ
この記事では、スクリプトによってフィードを表示できるようにしているだけですが、本当は、さらに一歩進んで、データ・トランスポート・メカニズムとしてスクリプト・タグを使用することもできます。フィードを取得するには、まず、JavaScript コードとしてエンコードされたフィード・リストが必要です。そこで、リスト11 に示されている list_js.php ページを作成しました。
##### リスト 11. list_js.php
<?php require_once 'rss_db.php'; header( 'Content-type: text/javascript' ); $rows = FeedList::getAll(); $feeds = array(); foreach( $rows as $row ) { $feed = "{ id:".$row['rss_feed_id']; $feed .= ", link:'".$row['url']."'"; $feed .= ", name:'".$row['name']."' }"; $feeds []= $feed; } ?> setFeeds( [ <?php echo( join( ', ', $feeds ) ); ?> ] );
このスクリプトをコマンドラインで実行すると、リスト12 の出力が表示されます。
##### リスト12. list_js.php からの出力
setFeeds( [ { id:1, link:' name:'Driving Sideways' }, { id:2, link:' name:'Slashdot' }, { id:3, link:' name:'Visible Light' }, { id:4, link:' name:'Socks on a Rooster' }, { id:5, link:' name:'Doxie Digest' }, { id:6, link:' name:'CNN.com' }, { id:7, link:' name:'CNN.com - World' }, { id:8, link:' name:'CNN.com - U.S.' } ] );
これが <script> タグに役立ちます。ブラウザーでこれを読み込むと、setFeeds 関数がフィードのリストとともに呼び出されます。この関数が <select> コントロールをセットアップして、最初のフィードを読み込みます。
また、XML の代わりに JavaScript コードで記事データを返す、read.php 関数に該当するものも必要です。リスト13 に、read_js.php ページを示します。
##### リスト 13. read_js.php
<?php require_once 'rss_db.php'; function js_clean( $str ) { $str = preg_replace( "/\'/", "", $str ); return $str; } FeedList::update(); $id = array_key_exists( 'id', $_GET ) ? $_GET['id'] : 1; $rows = Feed::get( $id ); $items = array(); foreach( $rows as $row ) { $js = "{ title:'".js_clean($row['title'])."'"; $js .= ", link:'".js_clean($row['link'])."'"; $js .= ", description:'".js_clean($row['description'])."' }"; $items []= $js; } ?> addFeed( <?php echo( $id ); ?>, [ <?php echo( join( ', ', $items ) ); ?> ] );
再び、このスクリプトをコマンドラインで実行すると、リスト14 の出力が表示されます。
##### リスト 14. read_js.php からの出力
addFeed( 1, [ { title:'War', link:' description:'The...' }, ... ] );
簡単にするために出力を切り詰めましたが、要点はわかると思います。addFeed 関数が、フィードの ID と JavaScript 形式でエンコードされた記事データとともに呼び出されます。
このような新しい JavaScript 対応サービスがあれば、これらのサービスを使用する新しいページを作成することもできます。リスト15 に、この新しいページを示します。
##### リスト 15. script.html
<html> <head> <title>Script Component Test</title> <style> ... </style> <script> var g_homeDirectory = ' function loadScript( url ) { var elScript = document.createElement( 'script' ); elScript.src = url; document.body.appendChild( elScript ); } function addFeed( id, articles ) { var ela = document.getElementById( 'elArticles' ); ela.innerHTML = ''; var elTable = document.createElement( 'table' ); var elTBody = document.createElement( 'tbody' ); elTable.appendChild( elTBody ); for( var a in articles ) { var title = articles[a].title; var link = articles[a].link; var description = articles[a].description; // Create elements as before... } ela.appendChild( elTable ); } function setFeeds( feeds ) { var elfl = document.getElementById( 'elFeedList' ); elfl.innerHTML = ''; var firstId = null; for( var f in feeds ) { var elOption = document.createElement( 'option' ); elOption.value = feeds[f].id; elOption.innerHTML = feeds[f].name; elfl.appendChild( elOption ); if ( firstId == null ) firstId = feeds[f].id; } loadFeed( firstId ); } function loadFeed( id ) { loadScript( g_homeDirectory+'read_js.php?id='+id ); } function getFeedList() { loadScript( g_homeDirectory+'list_js.php' ); } </script> </head> <body> <div class="rssControl"> <div class="rssControlTitle"> <select id="elFeedList" onchange="loadFeed( this.options[this.selectedIndex].value )"> </select> </div> <div id="elArticles"> </div> </div> <script> getFeedList(); </script> </body> </html>
このページは、元の index.html ページとよく似ています。ただし、loadXMLDoc 関数の代わりに、<script> タグを動的に作成する loadScript という新しい関数を使用しています。作成された <script> タグは、指定された URL から JavaScript コードを読み込みます。
これらのスクリプト・タグが、read_js.php ページと list_js.php ページを呼び出します。これらのページは、ホスト・ページの setFeeds 関数と addFeed 関数をコールバックする JavaScript コードを作成します。
このページをブラウザーで表示すると、図6 のようになります。
##### 図 6. データに対して <script> タグを使用する RSS リーダー
このコードの大きな利点は、誰でも「
View Source
(ソースの表示)」コマンドを使用してページのスクリプトを表示して、そのコードを自分のページにコピーできることです。そうすると、そのページでも JavaScript コードを返す
PHP サービスが使用されて、ページが更新されます。
## まとめ
この記事では、Web ページから動的にデータにアクセスして、Web ページ上で RSS リーダーを作成する 2 種類の手法を示しました。この記事で示した概念とコードを利用すると、ゼロから書き直さなくても、アプリケーションの機能を高めることができるはずです。それこそが Ajaxの真の価値です。Web テクノロジーに慣れている人にとって、サーバー・サイドにいくつかの新しいサービスを追加し、クライアント・サイドに小さなコードを追加することによって、ページのインタラクティビティを高めるのは簡単なことです。
## 動画デモ
developerWorks のデモがある記事はこの記事が初めて、という方のために、いくつか説明します。
developerWorks の記事でデモがある記事を読むのは今回が初めてという方のために、知っておいた方がよいことをいくつか説明します。
デモは、チュートリアルで説明したものと同じ手順を確認する 1 つの方法です。動画デモを見るには、「デモの表示」リンクをクリックしてください。デモはブラウザーの新しいウィンドウで開きます。それぞれのデモ画面の下には、ナビゲーション・バーがあります。これを使用すると、デモを一時停止したり、終了したり、巻き戻しや早送りをしたりすることができます。デモの解像度は 800 x 600 ピクセルです。もし画面の解像度がこの値と同じか、あるいはこの値よりも低い場合、デモの一部分はスクロールしなければ見えません。ブラウザーで JavaScript が有効になっていて、Macromedia Flash Player 6 またはそれ以降のプラグインがインストールされている必要があります。
#### ダウンロード可能なリソース
- このコンテンツのPDF
- Source code (x-ajaxrss-code.zip | 8KB)
#### 関連トピック
- Wikipediaの適切なページでAjaxについて読んでください。
- 「DHTML と XML を使った表現力豊かな Ajax スライドショー」が簡単に作成できます。同じ著者による記事で、クライアント・サイドのアニメーション・スライド・ショーを動的に作成する方法を学んでください (developerWorks、2006年4月)。
- RSS 1.0 標準を確認してください。
- RSS と密接な関係がある RDF (Resource Description Framework) について学んでください。
- developerWorks の XML ゾーンには、XML 開発者のための資料が他にも豊富に用意されています。
- PHP を学ぶのに最適な PHP ホーム・ページをご覧ください。