してはいけないことを主題にした記事を書くのはあまり楽しいことではありません。たいてい、それは間抜けた内容になるからです。つまり、記事の前半を説明に費やし、後半ではたった今説明したばかりの技術を使うのは愚かな考えだと説明するわけです。先月の記事はそういった類のもので (まだ読んでいない場合は、「参考文献」のリンクにアクセスしてください)、Ajax アプリケーションの要求のデータ・フォーマットとして XML を使用する方法を説明しました。
この記事が XML 要求について学んだ時間を挽回することになれば本望です。Ajax アプリケーションでは、送信データ・フォーマットとして XML を使用する理由はほとんどありませんが、その一方で、サーバーからクライアントには XML を戻すほうが望ましい理由は十分にあります。前回の記事で XML について学んだすべてのことが、この記事ではきっと、学んだ甲斐のあるものに見えてくるはずです。
サーバーからの XML 応答受信に関する技術的詳細を掘り下げる前に、サーバーが要求に応答して XML を送信することがなぜそれほど名案なのか (そして、クライアントが要求を XML で送信する場合との違い) を理解しておく必要があります。
前回の記事を思い出してください。クライアントが XML を使用する必要がほとんどないのは、クライアントは名前と値のペアで要求を送信できるためです。例えば、name=jennifer というように名前を送信したり、あいだにアンパーサンド (&) を加えるだけで name=jennifer&job=president のように名前と値のペアを続けることもできます。このように、クライアントは単純なテキストと名前と値のペアを使って、複数の値を持つ要求を簡単にサーバーに送信できます。XML が提供する追加構造 (そしてオーバーヘッド) が必要になることはめったにありません。
実際には、XML をサーバーに送信しなければならない理由はほとんどすべて次の 2 つの基本カテゴリーに分類できます。
- サーバーが XML 要求のみを許容するため。このような場合、他に選択肢はありません。この類の要求を送信するには、先月の記事で説明した基礎知識があれば十分です。
- XML 要求または SOAP 要求のみを許容するリモート API を呼び出すため。これは上記を特殊化したケースですが、このケース自体に説明の価値があります。非同期要求で Google や Amazon の API を使用する場合には、特別な考慮事項があるためです。来月の記事では、これらの考慮事項と、このような API に対して要求を行う例を紹介します。
サーバーは (標準的な方法では) 名前と値のペアを送信できません
名前と値のペアを送信すると、要求を送信する Web ブラウザーと、その要求に応答してサーバー・プログラムをホストするプラットフォームが連動して、名前と値のペアをサーバー・プログラムが扱いやすいデータに変換します。Java™ サーブレットから PHP、そして Perl から Ruby on Rails に至るまで、実質的にはあらゆるサーバー・サイド技術を使用してさまざまなメソッドを呼び出し、名前に基づいて値を取得することができます。つまり、name 属性の取得は取るに足らない作業です。
その逆となると、事情は変わってきます。サーバーが name=jennifer&job=president というストリングでアプリケーションに応答した場合、クライアントにはこの 2 つの名前と値のペアを分解し、それぞれのぺアを名前と値に分けるための標準化された簡単な方法がありません。そのため、返されたデータを手動で構文解析することになります。サーバーが名前と値のペアで構成された応答を返したとしても、そのような応答を解釈する難しさは、要素をセミコロンやパイプ記号、あるいはその他の標準外の書式制御文字で区切った応答と何ら変わりありません。
以上のことから、少なくとも応答に複数の値が含まれる場合には、クライアントへの応答にプレーン・テキストを使用し、クライアントにその応答を標準的な方法で解釈させる簡単な方法はないということになります。サーバーが 42 といった数字を戻すだけならプレーン・テキストは最適ですが、「ロスト」、「エイリアス」、「Six Degrees」という 3 つの TV 番組の最新視聴率をすべて同時に戻すとなったらどうでしょう。プレーン・テキストを使ってこの応答を送信するにはいろいろな方法がありますが (リスト 1 の例を参照)、どれも格別簡単とは言えません。いずれの方法にしても、解釈するにはクライアント・サイドで何らかの作業が必要となり、さらに標準化されてもいないためです。
リスト 1. TV 視聴率のサーバー応答 (各種バージョン)
show=Alias&ratings=6.5|show=Lost&ratings=14.2|show=Six%20Degrees&ratings=9.1
Alias=6.5&Lost=14.2&Six%20Degrees=9.1
Alias|6.5|Lost|14.2|Six%20Degrees|9.1
|
上記の応答ストリングを分解する方法を見つけ出すのはそれほど難しいことではありませんが、クライアントがストリングを構文解析し、セミコロン、等号、パイプ、アンパーサンドに基づいて分割する必要が生じます。これは、他の開発者が簡単に理解して維持できる堅実なコードを作成する方法とは程遠いものです。
サーバーが名前と値のペアでクライアントに応答するには標準的な方法がないということを理解すると、XML を使用する根拠がかなりはっきりしてきます。データをサーバーに送信する場合は、名前と値のペアは絶好の選択肢となります。なぜなら、サーバーとサーバー・サイド言語では名前と値のペアを容易に解釈できるためです。XML を使用してデータをクライアントに戻す場合も、これと同じことが言えます。XML を構文解析する場合の DOM の使用方法については以前の記事で説明しました。今後の記事では、XML を構文解析するもう 1 つの選択肢として、JSON を紹介する予定です。さらに、XML をプレーン・テキストとして処理して値を抽出することもできます。このように、クライアントがサーバーから XML 応答を受け取り、かなり標準的なコードでデータを抽出して使用するには、何通りかの方法があります。
おまけに、XML は一般的に極めて理解しやすいという特典があります。プログラマーであれば、例えばリスト 2 のデータを理解できるはずです。
リスト 2. TV 視聴率のサーバー応答 (XML バージョン)
<ratings>
<show>
<title>Alias</title>
<rating>6.5</rating>
</show>
<show>
<title>Lost</title>
<rating>14.2</rating>
</show>
<show>
<title>Six Degrees</title>
<rating>9.1</rating>
</show>
</ratings>
|
リスト 2 のコードには、特定のセミコロンやアポストロフィーが何を意味するかなどといった不可解さは、まるでありません。
この連載では Ajax 方程式のクライアント・サイドに焦点を絞っているため、サーバー・サイド・プログラムが XML で応答を生成する方法についてはあまり深く掘り下げないことにします。ただし、クライアントが XML を受信する場合に特別考慮しなければならない事項は知っておいてください。
まず、サーバーからの XML 応答を処理する基本的方法には、以下の 2 通りがあります。
- たまたま XML としてフォーマットされただけのプレーン・テキストとして処理する。
- DOM Document オブジェクトで表された XML 文書として処理する。
次に一例として、サーバーからの単純な XML 応答があるとします。リスト 3 は、上記で説明した TV 視聴率と同じものです (リスト 2 の XML と同じものですが、便宜上もう一度記載します)。このセクションでの説明には、このサンプル XML を使います。
リスト 3. サンプル用の XML 形式の TV 視聴率
<ratings>
<show>
<title>Alias</title>
<rating>6.5</rating>
</show>
<show>
<title>Lost</title>
<rating>14.2</rating>
</show>
<show>
<title>Six Degrees</title>
<rating>9.1</rating>
</show>
</ratings>
|
XML の処理方法として最も簡単な選択肢は、少なくとも新しいプログラミング技術を学ぶという点では、XML をサーバーから返されるすべてのテキストと同様に処理することです。つまり、基本的にはデータ・フォーマットを無視して、サーバーからの応答を単純に取り込みます。
この場合、サーバーが XML 以外の応答を送信してきたときとまったく同じように、要求オブジェクトの responseText プロパティーを使用します (リスト 4)。
リスト 4. XML を通常のサーバー応答として処理する方法
function updatePage() {
if (request.readyState == 4) {
if (request.status == 200) {
var response = request.responseText;
// response has the XML response from the server
alert(response);
}
}
}
|
このコード・フラグメントでは、updatePage() がコールバックで、request は XMLHttpRequest オブジェクトです。この結果、XML 応答は response 変数内にすべてがつながった形となります。この変数をプリントアウトすると、リスト 5 のようになります (リスト 5 のコードは通常 1 行に続いていますが、ここでは見やすいように複数の行で示しています)。
リスト 5. response 変数の値
<ratings><show><title>Alias</title><rating>6.5</rating>
</show><show><title>Lost</title><rating>14.2</rating></show><show>
<title>Six Degrees</title><rating>9.1</rating></show></ratings>
|
ここで最も注意すべき点は、XML がすべて一緒に実行されるということです。ほとんどの場合、サーバーでは XML のフォーマット設定にはスペースや改行を使わずに、リスト 5 のようにすべてを一続きにします。アプリケーションはほとんどスペースに配慮しないため、これが問題になることはありませんが、少々読みづらくなります。
この時点で、JavaScript の split 関数を使ってこのデータを分解し、基本的なストリング操作で要素の名前とそれぞれの値を取得することができます。もちろん、この作業は骨の折れるもので、しかも、この連載で以前かなりの時間を DOM (Document Object Model) の説明に費やしたという事実を無視しています。そこで覚えておいて欲しいのは、サーバーの XML 応答を使用して出力するにはresponseText を使えば簡単だということですが、コードはこれ以上記載しないことにします。次に説明するように、DOM を使用して XML データを取得できる場合には、この手法は使用しないでください。
サーバーの XML 形式の応答はテキスト形式の応答と同じように処理できますが、そのように処理するとよい理由はありません。まず、この連載を今まできちんと読んでいれば、DOM の使用方法がわかるはずだからです。DOM は JavaScript に適した APIで、XML の操作に使用できます。さらに、JavaScript と XMLHttpRequest オブジェクトが提供するプロパティーは、サーバーの XML 応答を受け取って DOM Document オブジェクトの形式にするにはまさに最適です。
これがどのように機能するかを確かめるには、リスト 6 を見てください。このコードはリスト 4 と似ていますが、コールバックは responseText プロパティーではなく、responseXML プロパティーを使用しています。XMLHttpRequest で使用できるこのプロパティーは、サーバーの応答を DOM 文書という形式で返します。
リスト 6. XML を XML として処理する方法
function updatePage() {
if (request.readyState == 4) {
if (request.status == 200) {
var xmlDoc = request.responseXML;
// work with xmlDoc using the DOM
}
}
}
|
DOM Document は、他の XML とまったく同じように操作できます。例えばリスト 7 のように、すべての show 要素を取り込むこともできます。
リスト 7. すべての show 要素を取得する方法
function updatePage() {
if (request.readyState == 4) {
if (request.status == 200) {
var xmlDoc = request.responseXML;
var showElements = xmlDoc.getElementsByTagName("show");
}
}
}
|
DOM を使い慣れていれば、この方法には馴染み始めているはずです。今までに学んだすべての DOM メソッドを駆使すれば、サーバーから受信した XML を簡単に操作できます。
もちろん標準の JavaScript コードに混ぜることもできます。例えばリスト 8 のように、すべての show 要素で繰り返すこともできます。
リスト 8. すべての show 要素での繰り返し
function updatePage() {
if (request.readyState == 4) {
if (request.status == 200) {
var xmlDoc = request.responseXML;
var showElements = xmlDoc.getElementsByTagName("show");
for (var x=0; x<showElements.length; x++) {
// We know that the first child of show is title, and the second is rating
var title = showElements[x].childNodes[0].value;
var rating = showElements[x].childNodes[1].value;
// Now do whatever you want with the show title and ratings
}
}
}
}
|
上記の比較的単純なコードでは、フォーマット設定されていないプレーン・テキストとしてだけではなく、XML としても XML 応答を処理し、ちょっとした DOM と単純な JavaScript を使用してサーバーの応答に対応しています。さらに重要なことは、コンマで区切られた値やパイプで区切られた名前と値のペアではなく、ここでは標準化された XML という形式を操作していることです。つまり、理に適っている場合には XML を使用し、XML を使っても意味がない場合 (サーバーに要求を送信するなど) には使用していません。
サーバー上で XML を生成する方法については十分説明していませんが、状況に対処する方法を自分自身で考え出せるように、あまり解説を加えずに簡単な例を紹介します。リスト 9 に示す単純な PHP スクリプトは、おそらく非同期クライアントからの要求に応答して XML を出力しています。
これは強引な手法で、PHP スクリプトは実際には XML 出力を手動で分割しているだけです。PHP には多彩なツールキットと API があり、その他のほとんどのサーバー・サイド言語でも XML 応答を生成できることがわかるはずです。少なくともこのリストを見れば、要求を生成し、XML で要求に応答するサーバー・サイド・スクリプトがどのようなものであるかがわかります
リスト 9. XML を返す PHP スクリプト
<?php
// Connect to a MySQL database
$conn = @mysql_connect("mysql.myhost.com", "username", "secret-password");
if (!conn)
die("Error connecting to database: " . mysql_error());
if (!mysql_select_db("television", $conn))
die("Error selecting TV database: " . mysql_error());
// Get ratings for all TV shows in database
$select = 'SELECT title, rating';
$from = ' FROM ratings';
$queryResult = @mysql_query($select . $from);
if (!$queryResult)
die("Error retrieving ratings for TV shows.');
// Let the client know we're sending back XML
header("Content-Type: text/xml");
echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
echo "<ratings>";
while ($row = mysql_fetch_array($queryResult)) {
$title = $row['title'];
$rating = $row['rating'];
echo "<show>
echo "<title>" . $title . "</title>";
echo "<rating>" . $rating . "</rating>";
echo "</show>";
}
echo "</ratings>";
mysql_close($conn);
?>
|
お好みのサーバー・サイド言語を使って、同じように XML を出力することができます。IBM developerWorks には、さまざまなサーバー・サイド言語を使用して XML 文書を生成する方法を理解するのに役立つ記事が多数記載されています。
XML をフォーマット設定されていないテキストとして処理するか、あるいは DOM を使用して処理するかという枠を超えて、XML を処理する選択肢として非常に人気のある JSON については触れておくべきでしょう。JSON は JavaScript Object Notation の略語で、JavaScript にバンドルされている無料のテキスト・フォーマットです。この記事では JSON について説明する余裕がないため、数ヶ月のうちに改めて取り上げる予定でいます。XML および Ajax アプリケーションについて話題にすると同時に JSON という言葉を耳にすると思いますが、これで、同僚が何について話しているのかがわかるようになるはずです。
概して、JSON を使って実行できることは DOM でも可能で、その逆も然りです。どちらを選択するかはほとんど好みの問題と、そして特定のアプリケーションにはどちらの手法が適切かによります。とりあえずは DOM を使用して、サーバーの応答を受信するというコンテキストでこの手法を使い慣れてください。JSON については、今後数回の記事で十分な時間を費やすつもりなので、今後のアプリケーションではこの 2 つの手法のどちらかを選択できるようになるはずです。それでは今後の連載もお見逃しなく。XML の詳細はまだまだ続きます。
前回の記事からここまでほとんどノンストップで XML について話してきましたが、それでもまだ、XML が Ajax 方程式に果す役割を表面的にかじっただけに過ぎません。次回の記事では、XML を送信したほうがいい特定の場合について詳しく説明します (さらに、XML を受信しなければならない場合も紹介します)。特に、Ajax との相互作用の観点から Web サービス (専有 Web サービスと Googls のような API の両方) を検討する予定です。
それまでの短い間、あなたに課せられた最大の宿題は、自分のアプリケーションではどのような場合に XML が意味をなすかを考えることです。多くの場合、アプリケーションが有効に機能していれば、XML は単なる技術の流行語でしかなく、頭痛の種になることもあります。アプリケーションで XML を使っていると言いたいがためだけに XML を使用するという誘惑には打ち勝たなくてはなりません。
一方、サーバーが送信してくるデータが限られている場合、あるいはコンマやパイプで区切られた奇妙なフォーマットでデータを送信してくる場合には、XML がまさに有効かもしれません。サーバー・サイド・コンポーネントが返す応答として、XML ほど頑強ではないことがほぼ確実な独自のフォーマットを使わずに、より標準的な方法である XML を使うようにサーバー・サイド・コンポーネントを変更することを考えてみてください。
とりわけ認識しておかなければならないのは、Ajax を取り巻く技術を知れば知るほど、決定には慎重さが求められるということです。Web 2.0 アプリケーションを作成するのは楽しいことですが (今後の記事では、ユーザー・インターフェースを再び取り上げ、高度な作業を紹介する予定です)、仲間を感心させるためだけに、有効に機能している Web ページに技術を投入することがないよう注意しなければなりません。優れたアプリケーションを作成できる能力があるなら、誘惑に負けずに自分の仕事に専念してください。それが終わってから、XML をさらに詳しく説明する来月の記事を読んでください。
学ぶために
-
「Ajax をマスターする」: 本連載のこれまでの記事を読んでください。
-
developerWorks XML ゾーン: 広範な技術に関する記事とヒント、チュートリアル、標準、そして IBM レッドブックについては、developerWorks XML ゾーンを参照してください。
-
developerWorks Web development ゾーン: Web 2.0、Ajax、Wiki、PHP、マッシュアップ、そしてその他の Web プロジェクトの資料が用意されています。
-
developerWorks Open source ゾーン: オープン・ソースの開発および実装に関する資料が用意されています。
-
「JSON を使ったキャッシング」(Bakul L. Patel 著、developerWorks、2006年10月): クライアント・サイドのキャッシュ検証メタデータについて説明しています。
-
xml.com: XML プログラマーとしての経験がまだ浅いという方は、まず、ここにアクセスしてください。XML に関する非常に分かりやすいオンライン資料が用意されています。
-
「Python モジュール xml2sql および dtd2sql の使用」(David Mertz 著、developerWorks、2001年6月): 人気の高い Python の XML 関連モジュールのデモで、データベースを作成してデータを入力する SQL ステートメントを生成できます。
-
「Build dynamic Java applications」(Philip McCarthy 著、developerWorks、2005年9月): Java パースペクティブを使って、サーバー・サイドからの視点で Ajax を説明しています。
-
「Java object serialization for Ajax」(Philip McCarthy 著、developerWorks、2005年10月): Java パースペクティブから、ネットワークでオブジェクトを送信する方法、および Ajax を操作する方法を説明しています。
-
「Call SOAP Web services with Ajax」(James Snell 著、developerWorks、2005年10月): この非常に高度な記事で、Ajax を既存の SOAP ベース Web サービスに統合する方法を詳細に検討してください。この記事では、Ajax 設計パターンを使用して Web ブラウザー・ベースの SOAP Web サービス・クライアントをインプリメントする方法を紹介しています。
-
World Wide Web Consortium の DOM ホーム・ページ: すべての DOM 関連情報は、ここから探してください。
-
The DOM Level 3 Core Specification: 使用可能なタイプとプロパティーから DOM の使用方法まで、各種言語でコア Document Object Model を定義しています。
-
DOM 用 ECMAScript 言語バインディング: JavaScript プログラマーが独自のコードから DOM を使用する際には、この Level 3 Document Object Model Core 定義の付録を参考にできます。
-
「Ajax: A new approach to Web applications」(Jesse James Garrett 著、Adaptive Path、2005年2月): Ajax の名前を作り出した記事です。すべての Ajax 開発者の必読書です。
-
developerWorks technical events and webcasts: 技術開発者を対象としたソフトウェア・ブリーフィングで最新情報を入手してください。
製品や技術を入手するために
-
『Head Rush Ajax』(Brett McLaughlin 著、O'Reilly Media、2006 年): ここに記載された Head First スタイルのアイデアを吸収してください。
-
『Java & XML 第2版』(Brett McLaughlin 著、O'Reilly Media, Inc.、2001 年):XHTML および XML 変換についての著者の考察を読んでください。
-
『JavaScript』(David Flanagan 著、O'Reilly Media, Inc.、2001 年): JavaScript と動的 Web ページの操作について広範に説明しています。次回の改版では、Ajax についての 2 つの章が追加されます。
-
『Head Firstデザインパターン』(Elizabeth Freeman、Eric Freeman 共著、O'Reilly Media, Inc.、2005 年): 標準 HTML および XHTML と、CSS の HTML への適用方法について詳しく説明しています。
-
IBM 試用版ソフトウェア: developerWorks から直接ダウンロードできるソフトウェアで、次の開発プロジェクトを構築してください。
議論するために
-
developerWorks blogs: developerWorks コミュニティーに参加してください。
-
Ajax forum on developerWorks: Ajax を学習または積極的に使用する Web 開発者のフォーラムで、Ajax に関する知識や情報を共有してください。

Brett McLaughlin氏は、Logo (小さな三角形を覚えていますか?) の時代からコンピューターの仕事をしています。現在の専門は、JavaおよびJava関連のテクノロジーを使ったアプリケーション・インフラストラクチャーの構築です。ここ数年は、Nextel Communications and Allegiance Telecom, Inc. でこれらのインフラストラクチャーの実装に携わっています。Brett氏は、Javaサーブレットを使ってWebアプリケーション開発のための再利用可能なコンポーネント・アーキテクチャーを構築するJava ApacheプロジェクトTurbineの共同設立者の1人です。同氏はまた、オープン・ソースのEJBアプリケーション・サーバーであるEJBossプロジェクトと、オープン・ソースのXML Web公開エンジンであるCocoonにも貢献しています。