XSLTはどのような言語で、何のために存在し、なぜこのように設計されたのでしょうか?これらの質問にはさまざまな答えがあり、初心者は、この言語が慣れ親しんできたどの言語とも異なっているため、しばしば混乱します。この記事では、XSLTを一連の流れの中でとらえようとしています。XSLTスタイル・シートを作成するように勧める代わりに、この言語がどのように生じたのか、どこが優れているのか、なぜ使うべきなのかを説明しています。

Michael Kay (mike@saxonica.com), Writer and programmer, Saxonica Limited

Author photo: Michael Kay

Michael Kayは、XMLの世界ではSaxon XSLTプロセッサーの作成者およびXSLT Programmer's Reference (Wrox社) の著者としてよく知られています。彼の背景 (かなり昔は博士だった) は、データベース・テクノロジーにあります。そのとき以来、彼は関係型でオブジェクト指向のフリー・テキスト・データベース・ソフトウェアであるCodasylを設計してきました。

この記事の執筆時において、Michaelは仕事の合間にあります (ただし、休んでいるわけではありません)。ICL (英国に拠点を持つITサービス企業) での24年間の勤務を終えたばかりで、すぐにSoftware AG に移り、将来のXML製品の方向を左右するアーキテクチャー・チームに加わる予定です。

著者は、自分がいつもWrox社の本のカバー写真のようにまじめな顔をしているわけではないことを証明するために、この写真を選びました。



2001年 2月 01日

わたしがもともとこの記事を書いたのは、Saxonに関する技術記事に必要な背景を説明し、典型的なXSLTプロセッサーで使用されるインプリメンテーション技法を考察することにより、ユーザーがスタイル・シートのパフォーマンスを最大化するのを助けるためでした。しかしながら、developerWorks の編集チームは、この概要がもっと広い範囲の読者にとっても興味深く、XSLT言語の独立した説明として別個に公開する価値があることを繰り返し私に説明し、その結果、今回の記事となりました。

XSLTとは

XSLT言語はWorld Wide Web Consortium (W3C) によって定義され、そのバージョン1.0は1999年11月16日に勧告として公開されました (参考文献を参照)。この言語の包括的な仕様とユーザー・ガイドは自著XSLT Programmers' Reference で提供しているので、この記事では扱いません。むしろ、この記事の目的は、大きな流れに中でXSLTが、どのような位置を占めるかを理解していただくことです。


XSLTの役割

XSLTの起源は、Web上での表示から独立した情報コンテンツへの渇望にあります。最初に定義されたように、HTMLは、段落、強調、および番号付きリストなどの抽象化された用語で表示を定義することにより、ある程度のデバイス非依存を実現しました。Webが商用に使用されるにつれ、出版社は印刷メディアと同様に出力品質を制御することを望むようになりました。その結果、フォントの明示やページ上の資料の絶対位置決めなど、具体的な表示制御が使用されることが徐々に増えてきました。不運ではありますが完全に予測可能だった副次作用として、同じコンテンツをディジタルTVセットやWAP電話などの代替デバイスに送達すること (出版業界の業界用語ではリパーパス という) がますます難しくなってきました。

印刷出版業界におけるSGMLの経験を取り込んで、XMLは1998年の初めに、表示から独立して構造化されたコンテンツを表すマークアップ言語として定義されました。固定された一連の概念 (段落、リスト、テーブルなど) を使用するHTMLとは異なり、XMLマークアップで使用されるタグは、完全にユーザー定義です。これは、関連する分野の物体 (人、場所、価格、日付など) を説明することを意図しています。HTMLのエレメントは本質的に活版印刷のものです (ただし、抽象化のレベルにおいて) が、XMLの目的はエレメントによって現実世界の物体を記述することです。たとえばリスト1は、サッカー・トーナメントの結果を表すXML文書を示しています。

リスト1. サッカー・トーナメントの結果を表すXML文書
<results group="A">
<match>
    <date>10-Jun-1998</date>
    <team score="2">Brazil</team>
    <team score="1">Scotland</team>
</match>
<match>
    <date>10-Jun-1998</date>
    <team score="2">Morocco</team>
    <team score="2">Norway</team>
</match>
<match>
    <date>16-Jun-1998</date>
    <team score="1">Scotland</team>
    <team score="1">Norway</team>
</match>
<match>
    <date>16-Jun-1998</date>
    <team score="3">Brazil</team>
    <team score="0">Morocco</team>
</match>
<match>
    <date>23-Jun-1998</date>
    <team score="1">Brazil</team>
    <team score="2">Norway</team>
</match>
<match>
    <date>23-Jun-1998</date>
    <team score="0">Scotland</team>
    <team score="3">Morocco</team>
</match>
</results>

このサッカーの結果をWebブラウザーで表示する場合、システムが適切なレイアウトで表示することは予期できません。データをブラウザー画面、TVセット、WAP電話、または紙上で表示する方法をシステムに伝える何らかの機構が他に必要です。ここで、スタイル・シートが登場します。スタイル・シートは、ソース文書でタグによって識別される情報エレメントを表示する方法を定義する一連の規則を宣言したものです。

W3Cは、2種類のスタイル・シート規格を定義しています。最初の規格はCSS (Cascading Style Sheets) として知られ、HTMLとともに広く使用されていますが、XMLとともに使用することもできます。CSSを使用すれば、たとえば、送り状を表示するときに支払勘定の合計を16ポイントのHelveticaの太字で示すことを指示することができます。ただし、CSSには、計算を実行したり、データの再配置やソートを行ったり、複数のソースからのデータを結合したり、ユーザーやセッションの特性に従って表示内容を個人用に調整したりする機能はありません。サッカーの結果の例では、CSS (あるいは、最新バージョンのCSS2。これは、まだ製品に完全にインプリメントされていない) はタスクを処理するのに十分強力とは言えません。これらの理由のため、W3Cはより機能が豊富なスタイル・シート言語の開発に乗り出しました。これは、XSL (Extensible Stylesheet Language) として知られ、SGMLコミュニティーで開発されたDSSSL (Document Style, Semantics,and Specification Language) から多くの着想を得ています。

XSLの開発中に (これは、DSSSLによってすでに予示されていた)、表示用のXML文書の作成時に実行するタスクを2つの段階 (変換とフォーマット設定) に分割できることが明らかになりました。変換とは、あるXML文書 (またはそのメモリー内表現) を別のXML文書に変えるプロセスのことです。フォーマット設定とは、変換されたツリー構造を2次元のグラフィカル表現 (または、1次元のオーディオ・ストリーム) に変えるプロセスのことです。XSLTは、最初の段階である変換を制御するための言語として開発されました。2番目の段階であるフォーマット設定の開発は、現在進行中です。ただし実際には、現在のほとんどの人々はXSLTを使用してXML文書をHTMLに変換し、HTMLブラウザーをフォーマット設定エンジンとして使用しています。これが可能なのは、事実上、HTMLがXMLボキャブラリーの一例にすぎず、XSLTがあらゆるXMLボキャブラリーをターゲットとして使用できるためです。

文書をユーザーに表示することを一切扱わない変換言語用のアプリケーションが多数あることが分かったため、変換とフォーマット設定を別々の言語に分離することは、非常に優れた決定であることが証明されました。XMLが電子ビジネスにおけるデータ交換構文として広く使用されるにつれ、データをあるXMLボキャブラリーから別のXMLボキャブラリーに変換するアプリケーションがますます必要になってきました。そのようなアプリケーションがあれば、たとえば、電子的なプログラム・ガイドからTVプログラムを抽出し、ペイ・パー・ビューのカスタマーに送る毎月の明細に挿入できます。同様に、多くの有用なデータ変換では、ソースとターゲットのボキャブラリーが同じです。これには、データのフィルター操作に加え、価格上昇の適用などのビジネス・オペレーションが含まれます。このため、データがXML構文でシステムを行き巡りはじめるとともに、XSLTはそのデータを操作するための偏在的な高水準言語になりはじめています。

前述の本において、わたしはXSLTとXMLの関係をSQLと表形式データの関係になぞらえています。関係モデルの強力なところは、データをテーブルに保管するというアイデアにあるのではなく、関係計算に基づいた、SQLで可能な高水準のデータ操作にあります。同様に、XMLの階層データ・モデルは、それ自体ではアプリケーション開発者にとってほとんど役に立ちません。これを強力なものとしているのは、XMLデータの高水準な操作言語であるXSLTです。


言語としてのXSLT

言語として見ると、XSLTはある意味でかなり奇妙なやつと言えます。わたしはこの記事において、この言語の設計について行われた決定の原理を示そうとは思いませんが、これらの決定をたどるなら、非常に論理的に、言語設計者が識別した要件に到達できます。詳細な説明については、わたしの本の第1章を参照してください。

以下に、XSLT言語の主要な特徴のいくつかを示します。

XSLTスタイル・シートはXML文書です。

この文書の構造は、XMLの不等号括弧タグの構文を使用して表されます。この構文はかなり気がきかず、この決定のためにこの言語はかなり冗長になっています。ただし、利点もあります。XMLの語い処理の道具 (たとえば、Unicode文字のエンコードとエスケープ、外部エンティティーの使用など) がすべて、自動的に使用可能になります。また、XSLTスタイル・シートは、容易に変換の入力や出力にすることができ、言語に再帰機能が備わります。希望するXML出力のチャンクをスタイル・シートに組み込むことも容易です。事実、多くの単純なスタイル・シートは、本質的に希望する出力文書のテンプレートとして作成し、可変データを入力から出力したり値を計算したりするための臨時の命令をテキストに組み込むことができます。これによりXSLTは、この単純なレベルにおいて、独自開発された既存のHTMLテンプレート言語によく似たものとなっています。

基本的な処理パラダイムはパターン・マッチングです。

この点において、XSLTは、Perlなどのテキスト処理言語の、1960年代のSNOBOLなどの言語にまでさかのぼることのできる長い伝統を継承しています。XSLTスタイル・シートは、それぞれが「この条件が入力で満たされたら、次の出力を生成する。」という形式を取っている、一連のテンプレート規則で構成されています。規則の順序は重要でなく、複数の規則が同じ入力に一致する場合は、競合解決アルゴリズムが適用されます。ただし、XSLTは、入力が1行ずつ順番に処理されないという点が、逐次形式のテキスト処理言語と異なっています。むしろ、入力XML文書はツリー構造として扱われ、各テンプレート規則はツリー内のノードに適用されます。次に処理するノードはテンプレート規則自体が決定できるため、入力は必ずしも元の文書における順序ではスキャンされません。


XSLTプロセッサーの操作

XSLTプロセッサーは、ツリー構造を入力として取り、別のツリー構造を出力として生成します。これは、図1で示されています。

図1. XSLTの入力と出力のツリー構造
図1

入力ツリー構造は、しばしばXML文書を構文解析することによって生成され、出力ツリー構造は、しばしば別のXML文書に逐次化されます。しかし、XSLTプロセッサー自体は、XML文字ストリームでなくツリー構造を操作します。この概念は、多くのユーザーにとって最初はかなり学問的に思えますが、より複雑な変換を実行する方法を理解する上で非常に重要であることが分かりました。まず、ソース文書におけるツリー構造と無関係な区別は、XSLTプロセッサーで処理できません。たとえば、属性が単一引用符と二重引用符のどちらで囲まれているかに応じて異なる処理を適用することはできません。これらはどちらも、同じ基本文書の異なる表現と見なされるためです。さらに小さな点として、入力エレメントの処理や出力エレメントの生成は、アトミック操作です。エレメントの開始タグと終了タグの操作を別々の操作に分離することはできません。これは、エレメントがツリー・モデルにおける単一のノードとしてアトミック表現されるためです。

XSLTでは、入力ツリー内のノードを参照するのにXPathという名前のサブ言語を使用します。XPathは、本質的に、XMLの階層データ・モデルに適した照会言語です。これには、ツリーを任意の方向にナビゲートしてノードを選択したり、ノードの値や位置に基づいて述部を適用したりする機能があります。また、基本的なストリング操作、数値計算、およびブール代数のための機能も組み込まれています。たとえば、XPath表現../@title では、現在のノードの親であるエレメントのtitle属性が選択されます。XPath表現を使用すれば、処理用の入力ノードの選択、条件付き処理における条件のテスト、および結果ツリーへの挿入用の値の計算を行えます。テンプレート規則では、特定のテンプレート規則が適用されるノードを定義するために、単純化された形式のXPath表現であるパターンも使用されます。XPathは別個のW3C勧告で定義されており、他のコンテキスト (特に、拡張ハイパーリンクを定義するためのXPointer構文) で再利用できるようになっています。

XSLTは、Lisp、Haskell、およびSchemeなどの伝統的な言語における関数型プログラミングの概念に基づいています。スタイル・シートは、本質的に純粋な関数であるテンプレートで構成されています。各テンプレートは、出力ツリーの断片を、入力ツリーの断片の関数として定義しており、いかなる副次作用もありません。この副次作用のない規則は、非常に厳密に適用されます (Javaなどの言語で作成された外部コードへのエスケープの場合を除く)。XSLT言語では、変数を定義できますが、既存の変数の値を変更することはできません。割り当てステートメントがないためです。多くの新しいユーザーが困惑するこの方針の目的は、スタイル・シートを増分的に適用することを可能にすることです。理論的には、この言語に副次作用がなければ、小さな変更を入力文書に加えたときに、全体の変換を最初から実行しなくても出力文書での結果の変化を計算できるはずです。ただし、現時点では、これは理論的な可能性にとどまっており、既存のXSLTプロセッサーでは実現していないことを述べておきます(注: XSLTは関数型プログラミングの着想に基づいていますが、関数を第1クラスのデータ型として扱う機能が欠けているため、まだ関数型プログラミング言語ではありません)。


サンプルのスタイル・シート

この段階までくると、例によってこの言語はずっと明確になるでしょう。リスト2は、サッカーの結果をリストする単純なスタイル・シートを示しています。

リスト2. サッカーの結果を表示する基本的なスタイル・シート
<xsl:transform
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    
<xsl:template match="results">
    <html>
    <head><title>
        Results of Group <xsl:value-of select="@group"/>
    </title></head>
    <body><h1>
        Results of Group <xsl:value-of select="@group"/>
    </h1>
    <xsl:apply-templates/>
    </body></html>
</xsl:template>
<xsl:template match="match">
    <h2>
        <xsl:value-of select="team[1]"/> versus <xsl:value-of select="team[2]"/>
    </h2>
    <p>Played on <xsl:value-of select="date"/></p>
    <p>Result: 
            <xsl:value-of select="team[1] "/> 
            <xsl:value-of select="team[1]/@score"/>,
            <xsl:value-of select="team[2] "/> 
            <xsl:value-of select="team[2]/@score"/>
    </p>
</xsl:template>
</xsl:transform>

このスタイル・シートは2つのテンプレート規則で構成されており、一方は<results> エレメントに一致し、他方は<match> エレメントに一致します (同音異義語 (訳者注: 「一致する」という意味のmatchと「試合」という意味のmatch) の使用をおわびします)。<results> エレメントに関するテンプレート規則は、ページのHTML見出しを出力してから、<xsl:apply-templates/> (それぞれが適切なテンプレート規則を使用する、現在のエレメントのすべての子エレメントを処理するXSLT命令) を呼び出します。この場合、<results> エレメントのすべての子エレメントは<match> エレメントなので、2番目のテンプレート規則を使用して処理されます。この規則は、試合の組み合わせ (「Brazil versus Scotland」の形式になっている) を識別する2次レベルのHTML見出しを生成してから、試合の日付と両チームの得点を示すHTML段落を生成します。

この変換の結果はHTML文書であり、図2で示されているようにブラウザーに表示されます。

図2. リスト2のスタイル・シートの結果
図2

これは、情報を表示する非常に直接的な方法です。ただし、XSLTはこれよりもずっと強力です。リスト3には、同じソース・データを操作できる別のスタイル・シートが含まれています。このスタイル・シートは、トーナメント終了時における各チームの順位を示すリーグ表を算出します。

リスト3. 各チームの順位を計算するスタイル・シート
<xsl:transform
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 version="1.0">
<xsl:variable name="teams" select="//team[not(.=preceding::team)]"/>
<xsl:variable name="matches" select="//match"/>
<xsl:template match="results">
<html><body>
   <h1>Results of Group <xsl:value-of select="@group"/></h1>
   <table cellpadding="5">
      <tr>
        <td>Team</td>
        <td>Played</td>
        <td>Won</td>
        <td>Drawn</td>
        <td>Lost</td>
        <td>For</td>
        <td>Against</td>
     </tr>
   <xsl:for-each select="$teams">
        <xsl:variable name="this" select="."/>
        <xsl:variable name="played" select="count($matches[team=$this])"/>
        <xsl:variable name="won" 
            select="count($matches[team[.=$this]/@score &gt; team[.!=$this]/@score])"/>
        <xsl:variable name="lost"
            select="count($matches[team[.=$this]/@score &lt; team[.!=$this]/@score])"/>
        <xsl:variable name="drawn"
            select="count($matches[team[.=$this]/@score = team[.!=$this]/@score])"/>
        <xsl:variable name="for"
            select="sum($matches/team[.=current()]/@score)"/>
        <xsl:variable name="against"
            select="sum($matches[team=current()]/team/@score) - $for"/>
        <tr>
        <td><xsl:value-of select="."/></td>
        <td><xsl:value-of select="$played"/></td>
        <td><xsl:value-of select="$won"/></td>
        <td><xsl:value-of select="$drawn"/></td>
        <td><xsl:value-of select="$lost"/></td>
        <td><xsl:value-of select="$for"/></td>
        <td><xsl:value-of select="$against"/></td>
        </tr>
   </xsl:for-each>
   </table>
</body></html>
</xsl:template>
</xsl:transform>

このスタイル・シートを完全に説明するスペースはここにありませんが、要約すると、このスタイル・シートはチームを表す1つの変数を宣言します。この変数の値は、トーナメントに参加している各チームの1つのインスタンスを含むノード・セットです。その後、各チームについて、勝ち、引き分け、負けの合計数と、得点および失点の合計数を計算します。図3は、ブラウザーに表示される結果出力を示しています。

図3. 順位を示すリスト3のスタイル・シートの結果
図3

この例の目的は、ソース・ドキュメントに出現するテキストにフォントやレイアウトを割り当てる以上の能力がXSLTにあることを示すことです。XSLTは完全なプログラム言語であり、表示または別のアプリケーションへの入力のために、ソース・データを任意の仕方で変換できます。


XSLTの利点

XSLTの使用を考慮すべきなのはなぜでしょうか?

XSLTを使用すれば、高水準の宣言型プログラミング言語が従来持っている利点を、XML文書の変換タスクに特化したかたちで得られます。

高水準言語の利点として通常挙げられるのは、開発の生産性です。しかしながら、実際の価値は、変更に対応する潜在能力にあります。XMLデータ構造を変換するためのXSLTアプリケーションは、低水準のDOMおよびSAXインターフェースを使用したプロシージャー型アプリケーションよりも、XML文書の詳細に対する変更に柔軟に対応できます。データベースの世界では、この機能はデータ独立性と呼ばれています。データ独立性の追求は、SQLなどの宣言型言語の成功と、旧来のナビゲーション型のデータ・アクセス言語の没落につながりました。XMLの世界でも確実に同じことが起こるでしょう。

他のすべての宣言型言語と同様、パフォーマンス上の欠点があります。しかし、大多数のアプリケーションにおいて、現在のXSLTプロセッサーのパフォーマンスはアプリケーション要件を十分満たすものであり、ますます向上しています。次の記事では、拙作のSaxon製品などのXSLTプロセッサーで使用されている最適化手法の種類について説明します。


まとめ

わたしがこの記事で示そうとしたのは、SQLが関係テーブルを操作するための高水準言語であるのと同じように、XSLTがXML文書を操作するための完全な高水準言語であるということです。これは単なるスタイル指定言語をはるかに超えたものであり、CSS (またはCSS2) よりもずっと強力であるということを理解してください。

すべてのビジネス論理がXSLTでコード化されたアプリケーションはすでに存在します。わたしが見た3層型のオンライン・バンキング・システムは、次のようになっていました。

  • すべてのデータは、XMLメッセージの形式でバックエンド操作システムから検索される。
  • ユーザーのアカウント・データは、オンライン・セッションの期間中、メモリー内にXML DOMの形式で表現される。
  • ユーザーに向けられたすべての情報は、まずXMLメッセージとしてパッケージされてから、ブラウザーの機能に応じてサーバーまたはクライアント上で実行されたXSLT変換によってHTMLに変換される。

このアプリケーションのデータはすべてXMLであり、すべての論理 (データ・アクセス論理、ビジネス論理、および表示論理) はXSLTでインプリメントされていました。すべてのプロジェクトでこのアーキテクチャーを採用することはお勧めできませんが、これを追求することには多くの利点があり、数年のうちにこのようなシステムは多くなるでしょう。

プログラミング言語として見ると、XSLTの多くの特徴 (XML構文の使用から、関数型プログラミング理論を基盤としていることまで) は、平均的なWebプログラマーにとって見慣れないものです。つまり、学習には多大の労力が必要で、しばしばフラストレーションがたまります。これは、初期の時代のSQLと同じことであり、XSLTがこれまでのほとんどのものとは根本的に異なっていることを確かに証明しています。しかし、あきらめないでください。これは非常に強力なテクノロジーであり、学習する努力を払うだけの価値が十分にあります。

参考文献

  • W3C発行のXSLT 1.0勧告。これは、XSLT言語の決定的な仕様です。
  • W3C発行のXPath 1.0勧告。これは、XSLTスタイル・シートで使用されるXPath表現構文の決定的な仕様です。
  • XSL-List。これは、MulberryTechが管理する、XSLTに関するすべてのことを扱う忙しいメーリング・リストであり、検索可能なアーカイブが存在します。
  • www.xslinfo.com。これは、XSLTに関する参考資料 (ソフトウェア、書籍、チュートリアルなど) へのリンクを含む、優れたハブ・ページです。

コメント

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=243378
ArticleTitle=XSLTはどのような言語か
publish-date=02012001