XSLT変換

XSLTについて。

XSLTとは?

XSLTは、XMLドキュメントを別のXMLドキュメントなどに変換するための言語で、XML用のスタイルシート言語であるXSLの一部(元々TCだった部分がFOと分離して設計されたXSLの一部)として使用するために設計されたスタイルシート言語です。

XSLTははじめ、Microsoft 社によって提案され、W3Cにより標準化されています。

PHP4では、拡張モジュールとして、Sablotronライブラリとlibxsltライブラリをサポートしています。また、Xalan等他のライブラリ(XSLTプロセッサ)のサポートも計画されているようです。

次の例は、libxsltモジュール(PHP 4: DOM XML/XSLT 関数)を使用したXSLT変換の例です。

<?php
$xmldoc = domxml_open_file("foo.xml");
$xsldoc = domxml_xslt_stylesheet_file("foo.xsl");
$result =  $xsldoc->process($xmldoc);
echo $xsldoc->result_dump_mem($result);
?>

次の例は、Sablotronモジュール(PHP 4: XSLT 関数)を使用したXSLT変換の例です。

<?php
$xh = xslt_create();
$result = xslt_process($xh, 'foo.xml', 'foo.xsl');
if ($result) {
  echo $result;
} else {
 die("Cannot process XSLT document.");
}
xslt_free($xh);
?>

PHP5では、libxsltを使用したXSLエクステンションを使用することができます。

<?php
// XMLソースをロードする
$xml = new DOMDocument;
$xml->load("foo.xml");
// XSLTソースをロードする
$xsl = new DOMDocument;
$xsl->load("foo.xsl");
// 変換の設定を行う
$proc = new XSLTProcessor();
$proc->importStyleSheet($xsl); // XSLルールを適用する
// XML に変換する
echo $proc->transformToXML($xml);
?>

注釈

  • 例は、PHP 4 を対象としています。PHP 5 では異なります。

XSLTクラス

クラスの作成経緯

本サイトを長くご愛顧下さっている方ならご存知でしょうが、本サイトでは数年前からサーバサイドXSLT変換による資源提供を始めました。それ以前には、ローカルにてXalan-jでXHTMLとHTMLに変換した出力をサーバ上でネゴシエイトさせたり、Perl言語で書いた自家製X/HTML変換スクリプトにて資源提供を行ったりしていました。

XSLT変換による資源提供を始めた当初、本サイトが現在利用しているサーバの管理者にSablotronのサポートをお願いし直にサポートされて以来、Sablotronを使用していましたが、その後もサーバの仕様が進化し続け、いつの間にかlibxsltもサポートされていました(何でも出来るサーバなので、Javaサーブレットって手段もあったのですが・・・、軽くて楽なPHPで落ち着きました)。

PHP4には、XSLT変換の為にSablotronとlibxsltライブラリの二種類の拡張モジュールがサポートされており、それを利用する為の関数が定義されています。しかし、使用するモジュールを変更する場合には、ソースコードの大幅な書き直しが必要になってしまいます。そこで、Sablotronとlibxsltの両ライブラリの為の関数をクラス化することで、両ライブラリを使用したソースコードの互換性を実現しました。

本サイトは、2008年8月にサーバリニューアルプロジェクトに伴い、PHP4からPHP5へ完全移行しました。以前のスクリプトは一切互換性がない為、新たにXSLエクステンションを使用した記述に変更しました。PHP5のXSLエクステンションはオブジェクト指向なので、クラス化しませんでした。以下で公開しているXSLTransformクラスはPHP4なので、PHP5では互換性がないのでご注意ください。

XSLTransformクラス

public class XSLTransform extends Object

構造

PHP 5
未公開

コンストラクタ

public void XSLTransform([String $module])
XSLT変換を行います。
引数
String $module
PHP XSL/T ライブラリ名 [sablotron|libxslt]

メソッド

public void loadStylesheet(String $xslSource)
XSLT変換に用いるXSL文章(文字列)を読み込む。
引数
String $xslSource
XSL文章
public void loadStylesheetFile(String $xslfile)
XSLT変換に用いるXSLファイルを読み込む。
引数
String $xslfile
XSLファイル
public void setParameter(String $qname, String $expression)
XSLTプロセッサに渡すパラメータを設定する。
引数
String $qname
QName
String $expression
expression
public void setLogHandler(String $logFile)
ログメッセージを書き込むためのログファイルを設定する。
引数
String $logFile
ログファイル名
public void transform(String $xmlSource, String $out)
XML文章にXSLT変換を適用する。
引数
String $xmlSource
XML文章
String $out
変換結果の出力ファイル
public void transformFile(String $xmlfile, String $out)
XMLファイルにXSLT変換を適用する。
引数
String $xmlfile
XMLファイル
String $out
変換結果の出力ファイル
public String getInfo(String $key)
XMLファイルにXSLT変換を適用する。
引数
String $key
取得したい情報 [name|version]
返り値
成功した場合にXSLTプロセッサに関する情報を返します。

クラスの使用例

次の例は、XSLTransformクラスを使用した簡単なサンプルです。

<?php
ini_set("include_path", "./");
require_once("org/purl/net/osamurai/xsl/XSLTransform.php");

$xslt = new XSLTransform("sablotron");
$xslt->setLogHandler("logfile.txt");
$xslt->loadStylesheetFile("foo.xsl");
$xslt->setParameter("param", "value");
$result = $xslt->transformFile("foo.xml");
echo $result;

unset($xslt);
?>

上の例では、XSLT変換にSablotronライブラリを使用します。XSLT変換にlibxsltライブラリを使用したい場合には、new演算子によりXSLTransformオブジェクトを作成する際に、第一引数にlibxsltを指定するだけです(デフォルト・第一引数未指定時は、XSLT変換にSablotronライブラリを使用します)。

注釈

ヒント??

仕組み

本サイトのXSLT変換による資源提供の仕組みには、他の自作クラス(CookieクラスContentNegotiationクラス等)も利用することで、利用者のUAに最適な形式を返すようにしています。

また、アクセシビリティ-やユーザビリティー等も考慮し、利用者自身が変換結果を設定できる仕組み(XSLT設定フォーム)も提供しています。この仕組みは実に単純で、様々な変化に対応する記述を行ったXSLファイルをひとつだけ(他の幾つかのXSLファイルには、xsl:output要素に異なる内容、xsl:importxsl:include要素でスタイルシートの結合くらい)用意しておき、利用者のリクエストデータをよくあるフォーム処理と同じ様に処理し、XSLTプロセッサに値(パラメータ)を渡す事で変化に富んだ出力をしています。どうです?想像よりも簡単な仕掛けでしょう。

ポイント

スタイルシート記述のポイントとしては、他のどんなXSLTプロセッサでも変換可能(独自拡張はなるべく使用しない)で変換後の出力に誤差がなるべく生じないように仕様に準じた記述を行っておく事。そうすれば、環境が変わっても困る事(テンプレート記述の修正等)は殆どありません。

他に、複数の書式のXML文書を扱う場合のポイントとしては、例えば、最上位要素がdocというXMLとbookというXMLのどちらもHTMLに変換しようとする場合、双方を一度別のXMLに変換(或いは一方の書式に変換)し、それを更に変換するという手法があります。私はこれを多段変換Multi-Step Transformationsと名付け、本サイトでも一部この手法を用いています。この多段変換の最大の利点は、例えば将来、最終的な出力となる(X)HTMLの内容を変更する場合(例えばナビゲーションの内容等)に、複数のXMLが各々別のスタイルシートで変換する必要がある場合、それら全てのスタイルシートの修正が必要になります。しかし、多段変換では、複数のXMLが共通して最終的な変換に用いるスタイルシートのみの修正だけで良いのです。

但し、(当然ながら)多段変換は単独変換より処理時間を要することが殆どです。そこは、製作者のテンプレート記述の力量の見せ所なのだと思います。