本文へジャンプ

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

送信されたすべての情報は安全です。

  • 閉じる [x]

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


送信されたすべての情報は安全です。

  • 閉じる [x]

ヒント: XSLTによるルックアップ・テーブル

Uche Ogbuji (uche@ogbuji.net), Principal Consultant, Fourthought, Inc.
Photo of Uche Ogbuji
Uche Ogbuji は、次世代の Web 技術を専門とするサービスの会社である、Uli, LLC の代表者です。Ogbuji 氏は XML、RDF、およびナレッジ管理アプリケーション用のオープン・ソース・プラットフォームである 4Suite の開発リーダーであり、Versa RDF 照会言語の開発リーダーでもあります。ナイジェリア出身のコンピューター・エンジニア兼ライターで、米国コロラド州ボールダー在住です。彼に関して詳しくは、彼のブログである Copia を見てください。

概要: ルックアップ・テーブルは、よく使われるプログラミング上の道具で、1つの値を別の値に効率的に変換するのに役立ちます。本稿では、XSLTにおいてルックアップ・テーブルを実現する方法を紹介します。XSLTに関する基本的な知識が前提となります。

日付:  2001年 2月 01日
レベル:  初級 この記事の原文:  英語
アクティビティー: 1831 ビュー
お気軽にご意見・ご感想をお寄せください: 


ルックアップ・テーブルは、プログラミングによって結果を出そうとすると非常に効率が悪かったり、それが不可能だったりする場合に、素早く結果を見つけ出すためによく使われる技法です。ルックアップ・テーブルは、キーを値に対応付けるためのマッピングで構成されます。ルックアップ・テーブルは、XSLTにおいても、他の言語の場合と同じように便利なものになり得ます。その理由は特に、XSLTはXMLツリーを変換することに高度に特化した言語なので、ストリングや数値の操作をあまり得意としていないところにあります。

本稿では、XSLTにおいてルックアップ・テーブルを使用する方法と、ルックアップ・テーブルをスタイル・シート内に使い易く収容する方法を紹介します。

サンプル課題

さて、リスト1に示す、宛名ラベルを表すソース文書について考えてみましょう。


リスト1: 宛名ラベル
                
<?xml version="1.0"?>
<labels>
 <label>
  <name>Thomas Eliot</name>
  <address>
   <street>3 Prufrock Lane</street>
   <city>Hartford</city>
   <state>CT</state>
  </address>
 </label>
 <label>
  <name>Ezra Pound</name>
  <address>
   <street>45 Usura Place</street>
   <city>Hailey</city>
   <state>ID</state>
  </address>
 </label>
 <label>
  <name>William Williams</name>
  <address>
   <street>100 Wheelbarrow Blvd</street>
   <city>Patterson</city>
   <state>NJ</state>
  </address>
 </label>
</labels>


. . . そして、この文書を基にして、リスト2のような、氏名と、その人が住んでいる州を要約したリストを生成することにします。


リスト2: 氏名と居住している州の要約
                
Thomas Eliot of Connecticut
Ezra Pound of Idaho
William Williams of New Jersey


ここで必要になるのは、州名の省略形 (たとえば "ID") を正式な名称(たとえば "Idaho") に対応付ける手段です。もちろん、ソース文書の作成者が最初から州の正式な名前を使ってくれていれば、何の問題もありません。しかし、ソース文書の形式をいつも自分で管理できるとは限らないわけです。


ルックアップ・テーブルを別個の文書に入れる

1つのソリューションは、ルックアップ・テーブル文書を作成するという方法です。その場合、ルックアップ・テーブルはリスト3のような簡単なものになります。


リスト3: ルックアップ・テーブル文書
                
<?xml version="1.0"?>
<states>
 <state><abbr>CO</abbr><name>Colorado</name></state>
 <!-- etc. -->
 <state><abbr>CT</abbr><name>Connecticut</name></state>
 <!-- etc. -->
 <state><abbr>ID</abbr><name>Idaho</name></state>
 <!-- etc. -->
 <state><abbr>NJ</abbr><name>New Jersey</name></state>
 <!-- etc. -->
</states>

この文書にはすべての州をリストしていませんが、文書の作り方はおわかりいただけるでしょう。リスト4に、states.xmlというルックアップ・テーブルを使って必要な結果を生成するスタイル・シートを掲載します。このスタイル・シートには、それぞれの変換ブロックごとにコメントとして英文字を入れておきました。これは、リストの後の補足説明に対応しています。


リスト4: 変換用のスタイル・シート (注釈入り)
                
<?xml version="1.0"?>
<xsl:transform
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 version="1.0">
 <xsl:output method="text"/>
<!-- A -->
 <xsl:key name="state-lookup" match="state" use="abbr"/>
<!-- B -->
 <xsl:variable name="states-top" select="document('states.xml')/states"/>
 <xsl:template match="label">
  <xsl:value-of select="name"/>
  <xsl:text> of </xsl:text>
<!-- C -->
  <xsl:apply-templates select="$states-top">
   <xsl:with-param name="curr-label" select="."/>
  </xsl:apply-templates>
 </xsl:template>
<!-- D -->
 <xsl:template match="states">
  <xsl:param name="curr-label"/>
  <xsl:value-of select="key('state-lookup', $curr-label/address/state)/name"/>
 </xsl:template>
</xsl:transform>

A. 最初に、スタイル・シート内でルックアップ・テーブルを表すキーを定義します。XSLTのキーでは、match 属性によって選択されるソース文書内のノードについて、名前付きインデックスが作成されます。キーは、use 属性から算出されます。ここで重要なのは、(document() 関数を使って) ロードされる各ソース文書ごとに別々のインデックスが用意されるという点です。key() 関数を使ってキーを照会すると、コンテキスト・ノードを含むソース文書のインデックスが使用されます。

B. この変数には、states.xml文書の文書エレメント(states) が設定されます。この場合、その文書がロードされる時点で、その文書のインデックスの生成がトリガーされます。ここで、元のソース文書 (宛名ラベルの文書) には、state-lookup というキーの定義にマッチするノードがないので、そのインデックスは空であることに注意してください。

C. この時点までで、宛名ラベルにある氏名と、"of" というテキストの生成が終わります。次に必要なのは、ルックアップ・テーブルを使って州の正式な名前を生成することです。それには、次のように記述すればよいと思うことでしょう。

<xsl:value-of select="key('state-lookup', address/state)/name"/>

しかし、すぐに思いつくこの書き方では、何も生成されません。なぜなら、すでに述べたとおり、キーが呼び出された時点で検索されるのは、コンテキスト・ノードを含む文書のインデックスだからです。この時点で、コンテキストは元のソース文書のlabelエレメントです。そして、state-lookup インデックスは、まだ空なのです。したがって、コンテキストをstates.xml文書に移す必要があります。その文書のインデックスに、必要な項目が入っているからです。

そのための最も直接的な方法は、xsl:apply-templates を使ってstates.xml文書内のノードを選択することです。それにはstates-top 変数が打ってつけだと思えるでしょう。しかし、現在のコンテキスト・ノードの位置も覚えておく必要があることに注意してください。そうしないと、現在処理中の人が住んでいる州の省略形を調べられないからです。この問題を解決するには、現在のノードをパラメーターとして次のテンプレートに引き渡すことができます。

D. ここまでくれば、キーを呼び出して必要な出力を生成するのは簡単です。パラメーターとして渡されたlabelノードのaddress 子エレメントのstate 子エレメントのストリング値を使ってルックアップ・テーブルを調べればよいのです。キーのルックアップの結果は、states.xml文書内の1つのstate エレメントを含んだノード・セット1つになります。したがって、最後に、そのエレメントのname 子エレメントを選択すれば、その中に、探している正式な州名が入っています。

このスタイル・シートを実際に実行してみてください。以前にお見せしたのと同じ、次のような結果が得られるはずです。 リスト5: キーを呼び出す

[uogbuji@borgia code]$ 4xslt labels.xml state-summary.xslt
 Thomas Eliot of Connecticut
 Ezra Pound of Idaho
 William Williams of New Jersey
[uogbuji@borgia code]$



ルックアップ・テーブルを変換スタイル・シートそのものに入れる

本稿で考えている課題は、ルックアップ・テーブルを保持することによって解決できました。しかし、XSLT変換スタイル・シートとルックアップ・テーブル文書という2つの文書をいつも提供しなければならないというのは不便かもしれません。幸いなことに、XMLの名前空間を利用すれば、ルックアップ・テーブルをスタイル・シートそのものの中にごく簡単に組み込むことができます。


リスト6: スタイル・シートの中のルックアップ・テーブル
                
<?xml version="1.0"?>
<!-- E -->
 <xsl:transform
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:s="http://states.data"
 version="1.0">
 <xsl:output method="text"/>
<!-- F -->
 <xsl:key name="state-lookup" match="s:state" use="s:abbr"/>
<!-- G -->
 <xsl:variable name="states-top" select="document('')/*/s:states"/>
 <xsl:template match="label">
  <xsl:value-of select="name"/>
  <xsl:text> of </xsl:text>
  <xsl:apply-templates select="$states-top">
   <xsl:with-param name="curr-label" select="."/>
  </xsl:apply-templates>
 </xsl:template>
<!-- H -->
 <xsl:template match="s:states">
  <xsl:param name="curr-label"/>
  <xsl:value-of select="key('state-lookup', $curr-label/address/state)/s:name"/>
 </xsl:template>
<!-- I -->
 <s:states>
  <s:state><s:abbr>CO</s:abbr><s:name>Colorado</s:name></s:state>
  <s:state><s:abbr>CT</s:abbr><s:name>Connecticut</s:name></s:state>
  <s:state><s:abbr>ID</s:abbr><s:name>Idaho</s:name></s:state>
  <s:state><s:abbr>NJ</s:abbr><s:name>New Jersey</s:name></s:state>
 </s:states>
</xsl:transform>

E. 組み込みルックアップ・テーブルのための名前空間を取り分けておく必要があります。そうしないと、XSLTがルックアップ・テーブルのエレメントを読み込んだ時点で、エラーが通知されます。XSLTプロセッサーは、xsl以外の名前空間に属する最上位エレメントを無視しなければならないのですが、この技法ではその事実をうまく利用するわけです。

F. ここでは、ルックアップ・テーブルのエレメントに対して名前空間の接頭部を使用する必要があります。

G. ここでは、document() 関数に空ストリングを渡すと、ソース文書としてスタイル・シートそのものが返される、という特別な規則を利用しています。ここでも、ルックアップ・テーブルのエレメントに対して名前空間の接頭部を使用する必要があります。このコードによって、スタイル・シートそのものがロードされて、組み込みルックアップ・エレメントのインデックスが生成されます。また、この技法の場合は、s:states エレメントが文書エレメントではなく、xsl:transform の子エレメントであることにも注意してください。したがって、変数のselect属性の内容に、その違いを反映させる必要があります。

H. Fと同じコメントが当てはまります。

I. これが、組み込みルックアップ・テーブルです。前のルックアップ・テーブルとの違いは、すべてのエレメントが名前空間に属していることと、s:states が文書エレメントではないことだけです。


結論

2番目のソリューションは、便利で美しい技法です。必要なのはスタイル・シートだけで、ただ値を検索するだけのために別個の文書を取り扱う手間が省けるのです。

この技法は、さまざまな方法で活用できます。ルックアップ・テーブルは、本稿で紹介した例のほかにも、"1/1/2001" といった日付を "January 1, 2001" といった形式に変換するためにも利用できるでしょう。

もちろん、ルックアップ・テーブルを別個の文書として用意したほうが便利な場合もあります。たとえば、XML文書内の通貨のデータを、XML対応のデータベースへの照会結果から取得したルックアップ・テーブルを利用して、米ドルから英ポンドに変換するアプリケーションの場合などです。

本稿で紹介した技法が読者の役に立つこと、そして、この技法に含まれているXSLTを活用するためのヒントから読者が何か1つでも学び取れることを期待しています。


参考文献

  • W3CのXSL のページには、XSLTの仕様、チュートリアル、各種の関連記事、XSLTのインプリメンテーションなど、XSLTに関連した多くの有用なリソースが掲載されています。

  • 本稿のサンプルで使用したXSLTプロセッサー4XSLTは、4Suite から入手できます。

著者について

Photo of Uche Ogbuji

Uche Ogbuji は、次世代の Web 技術を専門とするサービスの会社である、Uli, LLC の代表者です。Ogbuji 氏は XML、RDF、およびナレッジ管理アプリケーション用のオープン・ソース・プラットフォームである 4Suite の開発リーダーであり、Versa RDF 照会言語の開発リーダーでもあります。ナイジェリア出身のコンピューター・エンジニア兼ライターで、米国コロラド州ボールダー在住です。彼に関して詳しくは、彼のブログである Copia を見てください。

不正使用の報告のヘルプ

不正使用の報告

ありがとうございます。 このエントリーは、モデレーターの注目フラグが設定されました。


不正使用の報告のヘルプ

不正使用の報告

不正使用の報告の送信に失敗しました。


developerWorks: サイン・イン


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。 プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。 お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

表示名をお選びください

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

(半角英数字で3文字以上31文字以下にする必要があります)


「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


この記事を評価する

コメント

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=XML
ArticleID=243382
ArticleTitle=ヒント: XSLTによるルックアップ・テーブル
publish-date=02012001
author1-email=uche@ogbuji.net
author1-email-cc=

タグ

Help
このタグで、My developerWorks のすべてのタイプのコンテンツを見つけるために検索フィールドを使用します。

スライダーバーを使用することで、より多く(少なく)タグを表示します。

人気のタグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するトップのタグを表示します。

マイ・タグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するお客様ご自身のタグを表示します。

このタグで、My developerWorks のすべてのタイプのコンテンツを見つけるために検索フィールドを使用します。人気のタグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するトップのタグを表示します。マイ・タグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するお客様ご自身のタグを表示します。