PostgreSQLでXMLを処理してみよう!(第4回)(2)
XSLTスタイルシートの構成と書き方
ではここで、この記事で使用したスタイルシートの指定内容を説明しましょう。これはXMLデータを読み込んでHTML形式で出力するスタイルシートです。
※ここでは今回使用したXSLTスタイルシートについてある程度説明しますが、XSLTには他に多くの機能があります。それらについてはXSLTについて解説した書籍などを参照して学習してください。
変換指定を記述したXSLTスタイルシート自体もXML文書ですのでxml宣言(<?xml version=”1.0” encoding=”UTF-8”?>)から始まります。
それに続く<xsl:stylesheet>タグで始まり</xsl:stylesheet>タグで終わる部分がスタイル シート本体です。スタイルシート本体の中でxsl:という名前空間接頭辞付きの要素がXSLT規格で定められたものであり、XSLT要素と呼びます。図2では、XSLT要素に色を付けて区別を付けています。
xsl:という名前空間接頭辞が付かない要素(html、h1、tableなど)は、変換結果として生成される要素(結果ツリーの一部となる要素) です。図2で色が付いていない黒文字で記述された要素が生成される要素です。このように、XSLTでは、変換指定のためのXSLT要素と結果として生成する要素が混在しているので、XSLTの記述に慣れるまでは多少区別が付きにくいかもしれません。
では、以下に図2で示したXSLT要素を中心に、XSLTによる変換処理が元データであるソースツリーをたどりながらどのように結果ツリーを生成するのかについて説明します。
<xsl:stylesheet>要素
これはスタイルシート全体を括る要素であり、<xsl:stylesheet>要素の中に書いた様々なXSLT要素をXSLTプロセッサが解釈することにより様々な処理が行われ、ソースツリーから結果ツリーへと構造変換されていきます。
<xsl:output>要素
これは結果の出力形式を指定する要素です。XSLTでは結果ツリーをファイルへ出力する形式として、XML形式、HTML形式、テキスト形式の3種類を用意しています。今回はHTMLを指定しています。
<xsl:template>要素(1)
<xsl:template>要素は、ソースとなるxmlのどの要素(ノード)を、結果ツリーのどの要素(ノード)に変換するのかを指 定するための指定であり、XSLT記述の中核をなす指定です。XSLTでは、これをテンプレート規則(Template Rule)と呼びます。
図2では、<xsl:template>要素が2つありますが、最初の<xsl:template>要素は以下のようになっています。
-
<xsl:template match="/"> <html><xsl:apply-templates/></html> </xsl:template>
xsl:template要素のmatch属性は、ソースツリーのどのノード(変換元)に、内側に記述する命令を適用するかを指定する部分です。 「どのノードか」の指定はXPath式のサブセットとしての書き方を用います。ここでは第2回の記事でXPathのノード記述として説明した “/” (ルート要素)を指定しています。つまり変換元は、ソースツリーのルートノード(今回の場合work-record要素のさらに上にあるXMLデータには 表れないノード)です。
2行目に<html>要素がありますが、これで、変換元のルートノードに対し、変換結果としてhtml要素を生成するという指定になります。変換元がルートノードですから、これはつまり、「変換元のデータが与えられたら、まずはHTMLのデータを作り始めましょう」という指定になっているわけです。
<xsl:apply-templates>要素
<xsl:apply-templates>要素は、次にどのノードを処理するかをselect属性を指定して決め、そのノードを(他のテンプレートで)処理した結果をその場所に埋め込む(ここではhtmlの子要素となる)という指定です。
select属性を省略した場合は、現在の変換元ノードの子ノードが順次処理対象となります。今回はselect属性が省略されていますから、現在の変換元ノードであるルートノードの子ノードであるwork-record要素が処理対象となります。
<xsl:template>要素(2)
2番目の<xsl:template>要素も見てみましょう。これがwork-record要素を処理するテンプレート規則です。
-
<xsl:template match="work-record"> <h1>職務経歴一覧表</h1> <table frame="border" border="5" width="70%"> <tr><th>始</th><th>至</th><th>内容</th><th>役割</th></tr> <xsl:for-each select="career"> <tr> <td width="20%"><xsl:value-of select="period/start"/></td> <td width="20%"><xsl:value-of select="period/end"/></td> <td width="40%"><xsl:value-of select="content"/></td> <td width="20%"><xsl:value-of select="role"/></td> </tr> </xsl:for-each> </table> </xsl:template>
この<xsl:template>要素にはmatch=”work-record”として処理対象とするノードが指定されていますの で、このテンプレート規則が適用されるのはwork-record要素です。つまり、ルートノードの変換を行う 「<xsl:template>要素(1)」の中の<xsl:apply-templates>に対応して処理を行うのがちょう どこの「<xsl:template>要素(2)」ということになり、「<xsl:template>要素(2)」での変換結果が、「<xsl:template>要素(1)」の中の<xsl:apply-templates>の位置、つまりHTML要素 の内側に埋め込まれることになります。
さて、この<xsl:template>要素の中には、ソースツリーのwork-record要素に対応して生成す る<h1>,<table>,<tr>,<th>といった複数のHTML要素が指定されています。この ように、XSLTでは、元となる要素に対して、変換先は複数のまとまった要素群とすることもできます。ここでは、「職務経歴一覧表」というタイトルを HTMLのh1要素を使って表示し、その後、4つのカラム(始、至、内容、役割)を持つ表をtable要素で表そうとしています。
「始」、「至」、「内容」、「役割」といった表見出しの下に表示すべき経歴情報については、career要素の数だけ繰り返して生成します。この“要素の数だけ繰り返す”指定が次のxsl: for-each要素です。
<xsl:for-each>要素
<xsl:for-each select=”career”>は、select属性で指定された要素の回数だけ内側の処理を繰り返します。繰り返す処理はそれぞれhtmlのテーブルを生成するtr要素、td要素の中に書かれておりそこに結果が直接返されます。ここではselect=”career”となっていますので、ソー スツリーのwork-record要素の子要素のcareer要素に対してその個数分処理を繰り返します。つまり、今回のソースツリーにある2つのcareer要素に対して、その内側に書かれた4つの<td>要素を含む<tr>要素をそれぞれ生成します。
<xsl:value-of>要素
4つの<td>要素の中には<xsl:value-of select=”~”>というXSLT要素が指定されています。これはselect属性で指定されたノードの文字列値を取得します。ここではそれぞ れselect="period/start"、select="period/end"、select="content"、 select="role"と指定されていますので、career要素の中のperiod要素の子のstart要素の値、period要素の子のend要 素の値、content要素の値、role要素の値が、それぞれ「始」、「至」、「内容」、「役割」に相当する値とし て<td>~</td>の内側に埋め込まれることになります。
このような指定に沿って“鈴木花子”さんの<work-record>のXMLデータが変換され、結果ツリーが生成されます。それがHTMLデータとなって出力されるのです。
まとめ
今回は、XSLTスタイルシートの書き方とPostgreSQLでXSLT変換を実行する方法について説明しました。XMLデータに含まれている情報は、一部を取り出したり、別の形に変えて使うことが多いので、データベースで直接XSLT変換ができるのは大変便利です。
次回は、さらに、RDBデータをXMLデータとして取り出す方法についてSQL/XMLを説明します。
参考情報
今回は、PostgreSQLのバージョン8.3に含まれるxml2という追加モジュールを使ってXSLTを実行しました。
2009年7月1日公開のPostgreSQLバージョン8.4.0のマニュアルの「F.38.xml2」(http://www.postgresql.jp/document/pg840doc/html/xml2.html) では、“新しい標準APIのため、本モジュールはPostgreSQL 8.4で削除される予定ですので、...”となっており、今後XSLTについても追加モジュールという形ではなく、標準APIとしての実装になるようです が、実際にはPostgreSQL8.4.0にはxml2が含まれています。xml2の代替機能の完成までにはまだ時間がかかる様子なので、本稿では8.3のxml2機能を使って説明しました。
(2009年7月29日 公開)