[画像のクリックで拡大表示]

 前回はサーバーサイドでYahoo! ウェブ検索Webサービスにアクセスし,指定キーワードによる検索結果を取得するまでを見ました。今回は,サーバーサイドで得た結果をクライアントサイドで受け取り,ブラウザ上に表示してみることにしましょう。

クライアントサイドで処理結果を受け取ろう

 まずは,クライアントサイドでサーバーサイドでの処理結果を受け取るコードを見てみます(リスト1)。

リスト1●クライアントサイドのコード(yahoo.html)
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Yahoo! ウェブ検索Webサービス</title>
<script language="JavaScript">
<!--
 // [送信]ボタンをクリック時の処理を定義
function search() {
   // 非同期通信を行うためのXMLHttpRequestオブジェクトを生成
  try {
    xmlReq = new ActiveXObject("Microsoft.XMLHTTP");
  } catch(e) {
    xmlReq = new XMLHttpRequest();
  }
   // サーバーからの応答時の処理を定義(結果をページへ反映)
  xmlReq.onreadystatechange = function() {
    var msg = document.getElementById("result");
    if (xmlReq.readyState == 4) {
      if (xmlReq.status == 200) {
        var ctt="";
       var xmldoc=xmlReq.responseXML.documentElement;
       var nodes=xmldoc.childNodes;
       if(nodes.length==0){
         ctt="お探しのサイトは見つかりませんでした。";
       } else {
         for (i =0; i < nodes.length; i++) {
           var node=nodes.item(i);
           ctt += "<li><a target='_blank' href='" 
               + getNodeValue(node, "Url")
               + "'>" + getNodeValue(node, "Title") 
               + "</a></li>"
         }
       }
       msg.innerHTML=ctt;
      } else {
        msg.innerHTML="通信に失敗しました。";
      }
    } else {
      msg.innerHTML="通信中…";
    }
  }
   // サーバーとの通信を開始
  xmlReq.open("GET","yahoo.php?keyword="
              + encodeURI(document.fm.keyword.value), true);
  xmlReq.send(null);
}

 // ノードcurrent配下に含まれる要素nameのテキスト値を取得する関数
function getNodeValue(current ,name){
  var nodes=current.getElementsByTagName(name);
  var node=nodes.item(0);
  var txtNode=node.firstChild;
  return txtNode.nodeValue;
}
-->
</script>
</head>
<body>
<form name="fm">
  キーワード:
  <input type="text" name="keyword" size="15" maxlength="30" />
  <input type="button" value="検索" onclick="search()" />
  <hr />
  <ol type="1">
    <div id="result" />
  </ol>
</form>
</body>
</html>

 やや長いコードにも思われるかもしれませんが,ポイントとなるのはコード内太字の部分です。ほかの個所は,Ajaxプログラミングにおける定型的な処理そのままですので,忘れてしまったという方は,もう一度,連載第2~4回の解説を見直してみましょう。

 サーバーから送信されたXMLデータを取得するのは,XMLHttpRequestオブジェクトのresponseXMLプロパティの役割です。以前のサンプルで使用したresponseTextプロパティがサーバーから送信されたデータを文字列として取得したのに対し,responseXMLプロパティを使用することで応答データをDOMDocumentオブジェクトとして取得できます。

 DOMDocumentオブジェクトはXMLデータ(文書)を操作するためのオブジェクトです。XMLデータを読み込んだり操作したりするには,まずこのDOMDocumentオブジェクトを取得する必要があります。XMLデータ読み込みの詳細については次回に改めて解説しますので,ここではまず,図1でコードの概略の流れをイメージしてみることにしましょう。図と合わせて,コードの流れを追ってみてください。

 このようにXMLデータを読み込む場合には,タグの階層構造をツリーのように見立てて,最上位の要素(ルート要素)から順に下位要素へ向かってアクセスしていくのが一般的です。

 最終的に,結果XMLから<Title>要素(ページタイトル)と<Url>要素(URL)とを取り出し,リンク一覧として整形したものをinnerHTMLプロパティを使って<div>タグに反映させれば完了です。<div>タグに出力される最終結果の例を以下に挙げておきます(見やすいように適宜,改行とインデントを付与しています)。

  <li>
    <a target='_blank' href='http://www.wings.msn.to/'>
      サーバサイド技術の学び舎 - WINGS</a>
  </li>
  <li>
    <a target='_blank' href='http://www.web-deli.com/'>WebDeli - ホーム</a>
  </li>

 いかがですか? 以上の内容を理解できたら,実際に以下のURLからサンプル・アプリケーションを実行してみましょう。連載第5回冒頭に示したような結果を得られれば成功です。

  http://www.wings.msn.to/Ajax/yahoo.html

 今回はまず,コード全体を大ざっぱな枠組みから眺めてみました。すべてがすべてを理解できなくても構いません。まずは全体的な流れとイメージをつかみ取ることができればOKです。次回は引き続き本サンプルのXMLデータ読み込みの部分を詳述していきます。


特別コラム●Ajaxにおけるクロスドメイン問題

 前回/今回のサンプルを見て,あるいは,次のように思われた方もいたかもしれません。「サーバーサイドの役割って,ただ検索サービスにアクセスした結果をそのまま出力しているだけだよね。それなら,クライアントサイドでXMLHttpRequestオブジェクトで直接アクセスしてもいいんじゃないの?」

 良い思いつきのような気がします。しかし,残念ながら,これは不可です。というのも,本連載3回でも紹介したように,XMLHttpRequestオブジェクトではセキュリティの制限上,デフォルトで「外部サイトとの通信は禁止」されているからです。

 もちろん,ブラウザのセキュリティ制限を引き下げれば,外部サイトとの通信を実現することも可能ではあります。しかし,不特定多数のユーザーが使用するアプリケーションの場合,セキュリティ制限の引き下げを前提とするのは現実的ではないでしょう。

 そこで今回の例のように,外部サイトで公開されているサービスにアクセスする必要がある場合には,サービスにアクセスするための「サーバーサイド」のアプリケーション(「プロキシ」とも言います)を作成しておき,これに対して,クライアントサイドからアクセスするという方法を採る必要があるわけです。これによって,Ajaxアプリケーションから外部サービスを利用することが可能になります。

山田祥寛(やまだ よしひろ)

Microsoft MVP for ASP/ASP .NET。執筆コミュニティ「WINGSプロジェクト」の代表でもある。主な近著に「XMLデータベース入門」「PEAR入門」「Smarty入門」「10日でおぼえる入門教室シリーズ(Jakarta・JSP/サーブレット・PHP・XML)」(以上,翔泳社),「今日からつかえるサンプル集シリーズ(JSP&サーブレット・PHP5・ASP・XML)」(以上,秀和システム),「書き込み式 SQLのドリル」(ソシム),「JSP/PHP/ASPサーバーサイドプログラミング徹底比較」(技術評論社)など。最近では,IT関連技術の取材,講演,監修まで広く手がける毎日。