XML文書に対してUIを与えるためには、XSL(eXtensible Stylesheet Language)という仕様を利用します。これにより、単なるデータの集まりであったXML文書に対してビジュアルなインターフェイスを与えることができるようになります。
XMLドキュメントに対してUIを与えるには、XSLを純粋に利用するのが本来のスジといえるのですが、XSL標準のステータス(補足参照)などから判断した場合、現状のスペックのまま利用することをちゅうちょされる方も多いかと思います。そこで、ここでは、前回(「XSL/XSLTを利用したデータの変換と整列」)紹介した、XSLTといくつかの技術を組み合わせた形でのUI生成の手法を見ていくことにします。
補足:XSLの仕様について
このXSL仕様は、http://www.w3.org/TR/xsl/を見れば分かるように、本稿執筆現在では、Candidate Recommendation(勧告候補)(2000年11月21日)となっています。勧告候補とは、標準として仕様が確定する1歩前の段階で、もうすぐ勧告され標準化が完了するといった状態です。しかし、勧告される候補であるということから、いまの仕様を利用していく場合、将来にわたって変更されない保証はありません。利用する場合には、あらかじめ注意する必要があるでしょう。
さて、現実的なUI生成の方法はいくつかあります。ターゲットが一般的なWebブラウザ(Internet Explorerなど)であるときは、以下のような方法でしょう。
- XMLドキュメントをXSLTを用いてHTML形式に変換し、表示させる
- XMLドキュメントをXSLTを用いてHTML形式に変換し、CSSを利用してデザイン(フォーマット)する
つまり、XSLTを用いて、単純にHTML形式に変換し、UIとして生成する方法と、これにCSS(Cascading Style Sheet)の機能を用いてビジュアル的なフォーマッティングを行うという方法です。インターネット上のさまざまなサイトを見ていると、後者の方法を用いることが多いように見受けられます。
では、実際にこの手法を用いて、以下のXMLドキュメント(リスト1)にUIを付けていくことにしましょう。
<?xml version='1.0' encoding='UTF-8'
?>
<?xml-stylesheet type="text/xsl" href="review.xsl"
?>
<story>
<restaurant>
<name>XML ホテル</name>
<address>
<street>代々木 x-x-x</street>
<city>渋谷区</city>
<state>東京都</state>
</address>
<phone>03-1234-5678</phone>
</restaurant>
<review>
<rating stars="2.5">****</rating>
<date> June 1, 2001</date>
<reviewer>
<person>Ryo Nishiya</person>
</reviewer>
</review>
<body>
<p>
<summary>
このホテルは、
<city>渋谷区</city>
に存在している(本当は実在しません)小さなホテルです。名称は、
<self>XML ホテル</self>
といいます。
オーナーは、
<person>舞黒 太郎</person>
さんで、おいしい料理が自慢なのだそうです。
</summary>
</p>
</body>
<menu>
<appetizer>
<description>海鮮りんごスパゲティー</description>
<price>1500</price>
</appetizer>
<entree>
<description>魚と肉のムニエル</description>
<price>1000</price>
</entree>
</menu>
</story> |
リスト1 サンプルとなる宿泊施設のレビューをまとめたXMLドキュメント(review.xml) |
ここでは、仮に宿泊施設のレビューをまとめたXMLドキュメントがあったとします(書籍レビューでもいいかもしれませんね)。Webアプリケーションなどによって施設に対してのコメントや紹介などが寄せられて、これらの情報が、XMLドキュメントの中に蓄積されているというようなイメージです。このXMLドキュメントをブラウザで表示させると、図1のように、皆さんご存じのツリー構造のみが表示されます。このままだと、情報を参照しようとしたユーザーは何を意味しているのかを直感的に見分けることができません。
そこで、XSLを用いてドキュメントをXMLからHTML形式へ変換し、だれが見ても分かるようにしていくわけです。
ドキュメントの整形に関しては、前回の記事で紹介したXSLTの情報をもとにしていくとよいでしょう。ここでは、リスト2のようなXSLスクリプトを作成しました。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template>
<xsl:apply-templates />
</xsl:template>
<xsl:template match="text()">
<xsl:value-of />
</xsl:template>
<xsl:template match="/">
<HTML>
<HEAD>
<TITLE>
<xsl:value-of
select="story/restaurant/name" />
</TITLE>
</HEAD>
<BODY>
<TABLE WIDTH="580"
CELLSPACING="8">
<TR>
<TD
colspan="2">
<H1>
<xsl:apply-templates
select="story/restaurant/logo/*" />
<xsl:value-of
select="story/restaurant/name" />
</H1>
</TD>
</TR>
<TR>
<TD
WIDTH="120" VALIGN="top" STYLE="padding-top:2em">
<P
class="address">
Rating:
<IMG>
<xsl:attribute
name="src">rate<xsl:value-of select="story/review/rating/@stars"
/>.gif</xsl:attribute>
<xsl:attribute
name="title">rating: <xsl:value-of select="story/review/rating/@stars"
/> stars</xsl:attribute>
</IMG>
</P>
<HR
/>
<xsl:for-each
select="story/restaurant">
<P
class="address">
<xsl:value-of
select="address/street" />
</P>
<P
class="address"><xsl:value-of select="address/city"
/>, <xsl:value-of select="address/state" /></P>
<P
class="address">Res: <xsl:value-of select="phone"
/></P>
</xsl:for-each>
</TD>
<TD
class="body">
<P
class="tagline">
<xsl:value-of
select="story/review/date" />
</P>
<DIV
id="summary">
<P>
<xsl:apply-templates
select="story/body//summary" />
</P>
<P
class="tagline">
<A
href="javascript:show();">View complete review by <B>
<xsl:value-of
select="story/review/reviewer" />
</B></A>
</P>
</DIV>
<DIV
id="full" STYLE="display:none">
<xsl:apply-templates
select="story/body" />
<P
class="tagline">Review by <B>
<xsl:value-of
select="story/review/reviewer" />
</B>
<SPAN
class="dingbat">n</SPAN>
</P>
<P
class="tagline">
<A
href="javascript:hide();">View summary</A>
</P>
</DIV>
<DIV
id="menu">
<xsl:apply-templates
select="story/menu" />
</DIV>
</TD>
</TR>
</TABLE>
<P />
</BODY>
</HTML>
</xsl:template>
<xsl:template match="p">
<P>
<xsl:apply-templates />
</P>
</xsl:template>
<xsl:template match="person">
<SPAN class="person">
<xsl:apply-templates />
</SPAN>
</xsl:template>
<xsl:template match="city">
<SPAN class="city">
<xsl:apply-templates />
</SPAN>
</xsl:template>
<xsl:template match="self">
<SPAN class="self">
<xsl:apply-templates />
</SPAN>
</xsl:template>
<xsl:template match="menu">
<DIV class="menuhead">Menu
selections from the <I>
<xsl:value-of select="/story/restaurant/name"
/>
</I></DIV>
<TABLE CELLSPACING="0">
<TR>
<TD class="menuhead">Appetizers</TD>
</TR>
<xsl:apply-templates select="appetizer"
order-by="description" />
<TR>
<TD class="menuhead"><DIV
class="dingbat">u u u</DIV>Entrees</TD>
</TR>
<xsl:apply-templates select="entree"
order-by="description" />
</TABLE>
</xsl:template>
<xsl:template match="appetizer | entree">
<TR>
<TD class="menutext">
<xsl:value-of select="description"
/>
</TD>
<TD class="menutext"
VALIGN="bottom">
<xsl:value-of select="price"
/>
</TD>
</TR>
</xsl:template>
<xsl:template match="@*">
<xsl:copy>
<xsl:value-of />
</xsl:copy>
</xsl:template>
</xsl:stylesheet> |
リスト2 review.xmlを整形するためのXSLドキュメント(review-draft.xsl) |
このXSLスクリプトでは、前回紹介したようなロジックを同じように利用しています。例えば、
<TITLE>
<xsl:value-of select="story/restaurant/name" />
</TITLE> |
と記述されている部分は、HTMLのTITLEタグに、XMLドキュメントに存在するstoryエレメント内のrestaurantエレメントの中にあるnameエレメントの内容を与えるように指定されています。リスト1のXM文書の中でいうと、「XML ホテル」というデータが入っています。
また、
<IMG>
<xsl:attribute name="src">rate<xsl:value-of select="story/review/rating/@stars"
/>.gif</xsl:attribute>
<xsl:attribute name="title">rating: <xsl:value-of
select="story/review/rating/@stars" /> stars</xsl:attribute>
</IMG> |
という記述は、IMGタグのSRC属性やTITLE属性にそれぞれXML文書上にあるアトリビュート(属性)のデータ*1を与えるように指定しています。
*1:ここで指定されているattributeは、storyエレメントの中にあるreviewエレメント内のratingエレメントに含まれているstarsという属性が指定されています。@によってXMLドキュメントの内のattributeが指定されていることが見て取れます。
このように記述していくことによって、与えられたXMLドキュメントは、次第にHTMLのドキュメントへと変換されていきます。
前回は、これらXMLやXSLのドキュメントをDOMの命令を用いてプログラム上から変換していましたが、今回は、UIとして表示させることを1つの目的にしていますので、別の方法を紹介します。
XML文書の最初の部分には、「この文書はXML文書であり、エンコードはxxである」という宣言がなされています。これにもう1行、以下のような記述を追加します。
<?xml version='1.0' encoding='UTF-8'
?>
<?xml-stylesheet type="text/xsl"
href="review-draft.xsl" ?>
<story>
<restaurant> |
この1行は、「このXML文書においては、スタイルシートとしてtext/xslのタイプを持つreview-draft.xslというファイルを使用する」という意味になります。
これによって、前回紹介したような変換のためのロジック(プログラム)を作成することなく、XMLパーサが自動的にXSLを適用した結果をUI(Webブラウザ)へ返してくれます。
では、この行を追加した状態でXML文書をWebブラウザで参照してみることにしましょう。すると、図2のように表示されます。
いままでのようにツリー構造が表示されるのではなく、ちゃんと内容を理解することのできるUIが生成されていることがお分かりいただけるでしょう。しかし、このままですと、見た目に若干の問題が残ります。そこで、CSSの利用を検討します。HTMLへの変換が完了するということは、変換結果においてどのようなUIになるかが理解できているはずですので、必要となるスタイルをあらかじめXSL文書に対して与えてやることで、より見た目の整ったUIが生成できるはずです。
それでは、XSLドキュメント内に含まれるHTMLのHEADタグに、UIを整形するためのスタイル情報を埋め込むことにします。
(前略)
<HTML>
<HEAD>
<TITLE>
<xsl:value-of select="story/restaurant/name" />
</TITLE>
<STYLE>
BODY { margin:0px; background-color: #FFFFDD; width: 30em;
font-family: Arial, Helvetica, sans-serif; font-size: small; }
H1 { color: #0000FF;
}
P { margin-top:
.5em; margin-bottom: .25em; }
HR { color: #888833;
}
.address { text-align: right; font-size: xx-small; margin-top:.25em;
}
.tagline { font-style: italic; font-size: smaller; text-align:right;
}
.body { text-align: justify; background-color:
#FFFFDD; }
.dingbat { font-family: WingDings; font-style: normal;
font-size: xx-small; }
.person { font-weight: bold; }
.city { font-weight: bold; }
.self { font-style: italic; }
#menu { border: 2px solid black;
padding: 1em; background-color: #888833; }
.menutext { color: #FFFFDD; font-family: Times, serif;
font-style: italic;
vertical-align: top; text-align:center; }
.menuhead { color: #FFFFDD; font-family: Times, serif;
font-weight: bold;
vertical-align: top; text-align:center; margin-bottom: .5em; }
</STYLE>
</HEAD>
(後略)
|
リスト3 XSLドキュメント内にスタイルシートを埋め込む |
スタイル情報をご覧いただければ分かるように、タグやDIVタグの属性情報などによって背景色を設定したり、フォントのサイズなどを設定しています。こうすることで、スタイルシートによって生成されたHTML文書に対してリッチな見た目を提供できるようになります。
では、このファイルを仮にreview.xslと名前を付けて保存し、XMLドキュメントに指定していたスタイルシート情報のhref属性も以下のように修正します。
<?xml version='1.0' encoding='UTF-8'
?>
<?xml-stylesheet type="text/xsl" href="review.xsl"
?>
<story>
(以下略) |
すべての作業が完了したら、Webブラウザで表示させてみましょう。すると、図3のように表示され、単純にツリー構造が表示されていたという状況から進歩していることがご理解いただけるのではないでしょうか。
この方法を応用していくと、XML文書のためのUI生成に関してさまざまな考察が行えます。
単一のXML文書をデータとしてシステムに持たせておき、コンテンツリクエストをしてきたブラウザの情報を判断することで、返す文書形式を切り替えるという方法はその一例です。つまり、iモードやEZwebなどの端末やInternet Explorerなどからの要求を何らかの形で判断し、その結果、利用するスタイルシートをCHTML用、HTML用、WML用などという形で切り替えることで、単一のデータからさまざまなクライアントデバイスに対してUIを生成できるということになります。いままで、さまざまなクライアントのためにいくつものUIを生成しなければならなかった状況から、これで脱することができるのです。また、UIのためのロジックと実際のデータが明示的に分割化されていることによって、データを更新することですべてのデバイスに向けたデータを一括更新できますし、UIを変更したいときにも誤ってデータを壊してしまうこともありません。
今回ご紹介している例では、CSSにあたるHTMLのスタイル情報をXSLの中に直接埋め込んでいますが、もちろん、この情報も別ファイルという形で明示的な分離が実現できます。以下の例は、これらを実現したUIの生成方法にあたります(リスト4、5、6)。
<?xml version="1.0"
encoding="Shift_JIS"?>
<?xml-stylesheet type="text/xsl" href="spec.xsl"
?>
<spec updated="2000/01/05 00:00" by="Update Author">
<head>
<title>
XML /
XSL / CSS を利用したサンプル
</title>
<history>
<creation>
<date>2000/01/05</date>
</creation>
<change>
<date>no
changes</date>
<extent>Initial</extent>
</change>
</history>
<status> |
リスト4 データを格納するTemplate.xml
|
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
(中略)
<xsl:template match="/">
<HTML>
<HEAD>
<TITLE><xsl:value-of
select="spec/head/title"/></TITLE>
<LINK
rel="stylesheet" type="text/css" href="xmlweb.css"/>
<STYLE>
.interface
{margin:1em; border:2px solid rgb(52,128,184);} |
リスト5 HTMLのためのUI生成を行うspec.xsl
|
BODY { margin-left:
190px;
margin-right:10px;
background-image:url(images/xmlweb4.gif);
background-repeat:repeat-y;
font-family:"Verdana",
sans-serif;
font-size:xx-small;
}
#content { font-size:x-small;
padding-bottom: 2em;
}
.main { position:absolute;
top:80px;
left:200px;
}
#links { position:absolute;
top:108px;
left:45px;
} |
リスト6 美しいUI生成のためのxmlweb.css |
この例では、3つのファイルを1つのセットのように考えることができます。データは、Template.xmlによって格納されており、HTMLのためのUI生成にspec.xslが利用され、また、美しいUI生成のためにxmlweb.cssが用意されています。これらによって、XML文書に対して、見た目の整ったUIが提供できるようになっているのです(図4)。
今回紹介したサンプルのソースコードをまとめたものは、こちらからダウンロードできます。