Viper 2で学ぶXMLデータベース最新事情
Viper 2で学ぶXMLデータベース最新事情(2)

マッシュアップしたいけどPHPでDOMはイヤ!


日本アイ・ビー・エム
中林 紀彦
2007/11/22
最新のXMLデータベース実装となるViper 2(DB2 9.5)のリリースを機に、全4回の連載記事であらためてXMLデータベースの利点を考えてみる。そこで見えてきたものとは?(編集部)

“マッシュアップ”の追加にKさんの苦悩は続く

 CGM(ユーザー生成メディア)サイトを立ち上げることになったKさんの奮闘は相変わらず続いています。今回はプログラマとしてのKさんの苦悩をご紹介します。

 前回「なぜ彼はLAMPを捨てXML DBに走ったのか」で問題になっていたテーブル設計の問題を何とか乗り切って、Kさんはようやくベータ・サービスを開始できました。ベータ・サービスの開始後から注目度は高く、利用するユーザーからの意見もどんどん寄せられ、プロジェクトメンバーはうれしい限りでした。しかし、どの要件もテーブル設計を見直さざるを得ないほどの、当初のテーブル設計時には予想もつかなかったものばかり。寄せられた意見を反映するにはテーブルの分割などが必要で、修正の適用には多くの工数と時間を要し、適用時にもサービスの停止が必要でした。

 残念なことに一番多かった要望は、ログイン後のポータル画面でした。そこでは登録した興味のある分野のタグを持つコミュニティの新着情報を表示する仕様になっていたのですが、「興味のある分野を4つ以上登録したい」という声が多く、それならば制限をなくすためにと、結局正規化をしてテーブルを分割することになってしまいました(詳しくは第1回を参照ください)。

 11月某日にこのサービスの企画会議が開かれ、新たな機能を追加することになりました。現在の流行やユーザーから寄せられた意見を基に検討した結果、マッシュアップを活用したコンテンツの充実を目指すことになったのです。

 新しいコンテンツとして、メッセージの送信者が住む場所のお天気をメッセージの横に表示するというものでした(図1)。

図1 お天気を表示させるマッシュアップのイメージ
編集部注:@IT会議室を参考にイメージを作成しています。お天気アイコンは、後述するLivedoorの「お天気Webサービス」のものを使用しています。

 単純なアイデアですが、こういった細かいサービスがユーザーのリピート率、利用率を向上させるという意見で一致し、1週間後に機能を追加することになりました。また、携帯電話ユーザーの数も多いことから、この機能を携帯電話向けにも同時に公開することになりました。

 要件が決まればそこから先はKさんの仕事です。マッシュアップ用に、お天気のWebサービスを検討し、取得方法や実装方法といったアーキテクチャを練りました。PC用と携帯電話用のブラウザにも対応が必要なことから、XMLを使った実装に決め、早速実装に取り掛かりました(図2)。

 図2 マッシュアップのアーキテクチャ

 しかし……、以前にもDOM(Document Object Model)を使ったXMLアプリケーションを作った経験のあるKさんでしたが、エレメントの並べ替え(ソート)やノードの絞り込みなどの実装が非常に面倒ですごく手間がかかった記憶があり、1週間でプログラムの実装が終わるかどうか不安でした。実装すべき処理の流れは下記のとおりです。

  1. データベース(MySQL)から掲示板データを取り出してXMLを生成
  2. 掲示板データとお天気情報をマッシュアップして結果のXMLを生成
  3. 表示用のスタイルシート(XSLT)でそれぞれの形式に変換

 やはり、いざ実装に取り掛かるといろいろな問題が見えてきます。

課題1:データベース(MySQL)から取り出した結果セットのXML化

 使用する言語によって変わってきますが、大半の言語ではDOMを使用することになると思います。しかし対象の要素が多いとXMLを生成するのが大変です。

 リスト1はMySQLからの検索結果から、PHPのDOM関数を利用して、XMLドキュメントを生成する例です。一見、単純そうですが、実はそこに落とし穴が潜んでいます。よーく見てください。要素(Element)なのか属性(Attribute)なのか、そしてその要素(Element)がどのノードの子要素(Child)となるのかを、結果のXML(リスト2)をイメージしながらプログラミングをしなければいけません。ソースを見ただけで直感的に結果のXMLをイメージできないので、この部分は一苦労です。

// DOMオブジェクトの生成
$dom = new DOMDocument('1.0', 'UTF-8');
$root = $dom->createElement('result');
$dom->appendChild($root);

while ($row = mysql_fetch_array($result)) {
  // 要素(記事)の作成
  $item = $dom->createElement('記事');
  // 属性(記事ID)の設定
  $item->setAttribute(
    '記事ID', mb_convert_encoding($row[0], "UTF-8", "SJIS"));
  // ノードの追加
  $root->appendChild($item);
  // 要素(タイトル)の作成
  $element = $dom->createElement(
    'タイトル', mb_convert_encoding($row[1], "UTF-8", "SJIS"));
  // ノードの追加
  $item->appendChild($element);
  // 要素(投稿者)の作成
  $author = $dom->createElement('投稿者');
  // ノードの追加
  $item->appendChild($author);
  // 要素(ユーザ名)の作成
  $element = $dom->createElement(
    'ユーザ名', mb_convert_encoding($row[3], "UTF-8", "SJIS"));
  // 属性(ユーザID)の設定
  $element->setAttribute(
    'ユーザID', mb_convert_encoding($row[2], "UTF-8", "SJIS"));
  // ノードの追加
  $author->appendChild($element);
  // 要素(地域)の作成
  $element = $dom->createElement(
    '地域', mb_convert_encoding($row[4], "UTF-8", "SJIS"));
  // ノードの追加
  $author->appendChild($element);
}
リスト1 PHPのDOM関数を使って結果セットからXMLを生成する

  <記事 記事ID="10">
    <タイトル>テーブルの頻繁な設計変更を楽にしたい</タイトル>
    <投稿者>
      <ユーザ名 ユーザID="10">Kさん</ユーザ名>
      <地域>横浜</地域>
    </投稿者>
  </記事>
リスト2 リスト1で生成するXMLの完成型

  1/3

 Index
連載:Viper 2で学ぶXMLデータベース最新事情(2)
 マッシュアップしたいけどPHPでDOMはイヤ!
Page 1
・“マッシュアップ”の追加にKさんの苦悩は続く
・課題1:データベース(MySQL)から取り出した結果セットのXML化
  Page 2
・課題2:DOMを使ったXMLデータの検索
・課題3:XMLデータの並べ替え(ソート)や集計
  Page 3
・やっぱりXMLにはXMLデータベースとXQueryが素直でいいね
・時間が余ったので、追加のマッシュアップ


Viper 2で学ぶXMLデータベース最新事情



Database Expert フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Database Expert 記事ランキング

本日月間