レベル: 中級 Jake Miles, Freelance writer and developer, Twistage Inc.
2008年 11月 18日 この記事で説明するのは、PHP 5 で動作し、ソースである XML 文書に XSLT スタイルシートのチェーンを簡単に適用できるようにするフレームワーク、Butterfly を作成する方法です。このフレームワークを使用することで、XML 文書から変換した結果をそのままキャッシングできるようになります。Java™ ベースの Apache Cocoon プロジェクトに端を発し、ある形式から別の形式へのデータ変換 (毛虫から蝶 (Butterfly) への変身) を管理し、その変換結果を保存することから、この極めて軽量になったフレームワークは Butterfly と呼ばれています (訳注: Apache Cocoon プロジェクトの Cocoon は繭 (まゆ) という意味です)。Butterfly フレームワークでは、スタイルシート変換のチェーンを定義する XML 構成ファイルを設定し、Butterfly オブジェクトをインスタンス化して、そのそれぞれで XSLT 変換チェーンの結果を生成することができます。この記事では、Butterfly フレームワークの概要を具体的に説明することで、フレームワーク設計の本質全般についても検討することになります。
はじめに
PHP 5 の XSL モジュールでは、XSLT スタイルシートを XML 文書に適用して、XML データを他のタイプのテキスト文書に変換することができます。変換後の文書の構造としては、別の XML 構造や HTML にすることも、プレーン・テキストやさらには Java や他のプログラミング言語を含めた他のあらゆる構造にすることができます。またソース・テキストやターゲット文書の構造に関わらず、XSLT の問題に特有のあらゆるプログラムを作成することができます。XSLT プロセッサー・オブジェクトを作成し、変換を適用するには、この記事で使用する PHP コードだけで十分です。
 |
よく使われる頭字語
- API: application programming interface
- HTML: Hypertext Markup Language
- PHP: PHP Hypertext Preprocessor
- XML: Extensible Markup Language
- XSL: Extensible Stylesheet
- XSLT: Extensible Stylesheet Transformations
|
|
PHP で XSLT スタイルシートを XML に適用する仕組みは通常は同じなので、ビジネス固有のコードからこのプロセスをリファクタリングして、より再利用しやすいコードにすることが可能です。この記事では、XSLT 文書のチェーンを処理する再利用可能な軽量の PHP フレームワーク、Butterfly の概要を説明します (Butterfly をダウンロードするには、「参考文献」を参照してください)。ただし、ここで説明する Butterfly フレームワークは、http://jakemiles.com/butterfly でホストされているプロジェクトのことで、同じ名前を持つ他の Java ベースの Web アプリケーション・フレームワークとは無関係なのでご注意ください。チェーンはソースである XML 文書から始まり (必ずしも 1 つのファイルとは限りません)、この文書に一連の XSLT スタイルシートを適用して最終的な文書を生成します。この機能は、XSLT スタイルシートのパイプラインを処理して最終文書を生成する Java ベースのフレームワーク、Apache Cocoon プロジェクトが提供する機能のほんの一部です。
最終文書が Web ページの場合、XSLT スタイルシートを処理する際にはパフォーマンスが 1 つの懸念事項となります。文書のデータ量が少なかったり、単純なスタイルシートであればパフォーマンスが問題になることはありませんが、何千もの要素がある大量のデータ・セットの場合、一連のスタイルシートをページがロードされるたびに適用するのでは、ページのロードに時間がかかるだけでなく、メモリーとサーバーの処理能力を大量に消費することになるからです。
このようなパフォーマンス問題に対するソリューションは単純で、キャッシュを使用することです。つまり、Web サーバーがすぐに対応できるように XSLT 変換の結果を静的 HTML ページとしてキャッシュに入れ、XSLT 変換の完全なチェーンを実行するのはソース文書、あるいはスタイルシートのいずれかが変更されたときだけにするというソリューションです。このキャッシング・メカニズムは関連する特定の XML や XSLT に特有のものではないので、このフレームワークでは一般的メカニズムとして処理することができます。
XSLT スタイルシートを処理するときに考えられるもう 1 つの問題は、ソースである XML に関する問題です。XML はファイルから提供されることもあれば、SQL データベースから提供されることもあります。そのため、フレームワークは複数のデータ・ソースに対応できるだけの柔軟性を持ち合わせていなければなりません。
初期段階のフレームワーク
オブジェクト指向のフレームワークを設計するときには、基本的にメソッドとクラスという 2 つの抽象化ツールを使用することができます。継承可能にしなければならないすべてのもの、つまり将来、新しい類の振る舞いを可能にしたいものについては、メソッド呼び出しまたはクラスとして抽象化しなければなりません。そうすることにより、ポリモーフィズムを利用して、実行時に同じメソッドを公開する別のクラスと交換することが可能になります。フレームワークがクラスで溢れかえってきたらファクトリー・クラスを追加し、このファクトリー・クラスによって複数のクラスを共通の組み合わせにまとめ、共通して使える単純化した API を提供することができます。
フレームワークを作成するための実践的な方法は、最初にコアの機能を作成し、それからその機能に構造を適用することで継承可能にし、インターフェースを単純化する方法です。この記事に記載しているような簡潔なコードにするためには、まずコード全体で使用している 2 つのコア・インターフェース、ButterflyDocument と ButterflyXmlDocument に注目してください (リスト 1 を参照)。
リスト 1. コア・インターフェース、ButterflyDocument と ButterflyXmlDocument
interface ButterflyDocument {
function getContents();
function writeContents();
}
interface ButterflyXmlDocument extends ButterflyDocument {
function getDom();
}
|
ButterflyDocument は、読み取り/書き込み可能なコンテンツが含まれるテキスト文書を表します。リスト 1 では、この文書のコンテンツを getContents() がストリングとして返し、writeContents() が標準出力に書き込みます。もう一方の ButterflyXmlDocument は XML 文書を表します。ButterflyXmlDocument はButterflyDocument を継承したもので、この文書の XML コンテンツを表す DOMDocument オブジェクトを返す getDom() メソッドが定義されています。
この 2 つのコア・インターフェースとは別に、今度はフレームワークのコア機能である ButterflyTransformer クラスに目を向けてください。このクラスには XSLT スタイルシートを XML 文書に適用するという基本的な役割があります (リスト 2 を参照)。
リスト 2. ButterflyTransformer
class ButterflyTransformer {
private $processor;
public function __construct ($xslSource) {
$this->processor = new XSLTProcessor();
$this->processor->importStylesheet ($xslSource->getDom());
}
public function transformToFile ($xmlSource, $filepath) {
$file = fopen ($filepath, "w");
fwrite ($file, $this->processor->transformToXml ($xmlSource->getDom()));
fclose($file);
}
public function transformToString ($xmlSource, $filepath) {
return $this->processor->transformToXml ($xmlSource->getDom());
}
}
|
リスト 2 の ButterflyTransformer は XSLT スタイルシートを表す ButterflyXmlDocument オブジェクトを取り、PHP 5 の XSL モジュールを使用してこのスタイルシートを XML データ文書に適用します。まずコンストラクターが XSLTProcessor オブジェクトを作成し、指定された XSLT スタイルシートをこのオブジェクトにインポートします。続いて transformToFile() が、別の ButterflyXmlDocument オブジェクトによって表された XML 文書にスタイルシートを適用し、変換後のコンテンツを指定されたファイル・パスに書き込むという流れです。
チェーンとキャッシングの追加
ButterflyTransformer の次に注目するのは、Butterfly クラスです。このクラスは一連のスタイルシート変換 (Apache Cocoon の用語を借りると、パイプライン) に含まれる 1 つのチェーンを表すだけでなく、コアとなるキャッシング・ロジックも扱います (リスト 3 を参照)。
リスト 3. Butterfly クラス
class Butterfly implements ButterflyXmlDocument {
private $transformer;
private $xmlDoc;
private $cache;
public function __construct ($transformer, $xmlDoc, $cache=null) {
$this->transformer = $transformer;
$this->xmlSource = $xmlDoc;
$this->cache = $cache;
}
public function getDom() {
return $this->getTransformedDoc()->getDom();
}
public function getContents() {
return $this->getTransformedDoc()->getContents();
}
public function writeContents() {
$this->getTransformedDoc()->writeContents();
}
protected function getTransformedDoc() {
return ($this->cache != null
? $this->getTransformedCache ()
: $this->getTransformedString ());
}
protected function getTransformedCache () {
if (! $this->cache->isPresent()) {
$this->transformer->transformToFile ($this->xmlSource,
$this->cache->getFilepath());
}
return $this->cache;
}
protected function getTransformedString () {
return new ButterflyXmlString
($this->transformer->transformToString ($xmlDoc));
}
}
|
Butterfly クラスのコンストラクターが引数に取るのは、コア XSLT 変換ロジックを操作するための ButterflyTransformer オブジェクト、ソースである XML を表すための ButterflyXmlDocument、そしてキャッシュされた変換済み文書を保管および生成するための ButterflyCache オブジェクト (オプションの引数) です。Butterfly 自体は ButterflyXmlDocument を実装することに注意してください。つまり、getContents()、writeContents()、getDom() メソッドを公開するということです。そのため、XSLT 変換チェーンを Butterfly オブジェクトのチェーンとして実装し、それぞれのオブジェクトが次のオブジェクトのソース・オブジェクトとして機能させることができます。
Butterfly を使用するには、呼び出し側がこれらのオブジェクトを指定してコンストラクターを呼び出し、次に getContents() または writeContents() のいずれかを呼び出して、変換後の結果ストリングを取得するか、あるいは変換後の結果を直接標準出力に書き込みます。
キャッシング・ロジックを操作するのは getTransformedDoc() と getTransformedCache() です。コンストラクターはキャッシュ・オブジェクトをオプションの引数として取ることを思い出してください。そのためこのコンストラクターはキャッシュ・オプションには手を付けずに、呼び出し側がキャッシングやフレームワークの構成を懸念することなく XSLT 変換を適用する Butterfly オブジェクトを作成できるようにしています。つまり、getTransformedDoc() は Butterfly にキャッシュ・オブジェクトが設定されているかどうかを調べ、設定されている場合には getTransformedCache() を呼び出してキャッシュに入れられているものを扱い、設定されていない場合には getTransformedString() を呼び出すということです。いずれのメソッドにしても、ButterflyDocument オブジェクトを返すことに注意してください。
ソース文書
ButterflyTransformer クラスと Butterfly クラスには、フレームワークのコア機能が含まれています。次のステップで実装するのは ButterflyXmlDocument です。ButterflyXmlDocument は Butterfly そのものではないため、デリゲート・チェーンは、Butterfly の writeContents() メソッドまたは getContents() メソッドを呼び出した時点で終了します。最もよくあるケースは、XSLT スタイルシートを XML ファイルに適用するケースなので、このタイプの文書を表す ButterflyFile クラスを作成します (リスト 4 を参照)。
リスト 4. ButterflyFile クラスの作成
class ButterflyFile implements ButterflyDocument {
private $filepath;
public function __construct($filepath) {
$this->filepath = $filepath;
}
public function getFilepath() {
return $this->filepath;
}
public function isPresent() {
return file_exists ($this->filepath);
}
public function getContents() {
return file_get_contents($this->filepath);
}
public function writeContents() {
$file = fopen($this->filepath, "r");
fpassthru($file);
fclose($file);
}
public function delete() {
unlink ($this->filepath);
}
}
|
上記は、ButterflyXmlDocument クラスの具象実装に向けての第一歩です。このクラスは ButterflyXmlDocument の親インターフェースである ButterflyDocument しか実装しません。なぜなら変換結果が XML にならない可能性を考えると、フレームワークはソースである XML 文書とプレーン・テキスト文書の両方を表す必要があるためです。そこで、ファイルを囲む標準ラッパー・クラスとなるのが ButterflyFile です。ファイルの完全パスを指定して作成するこのクラスは、Butterfly クラスによって呼び出される isPresent()、getContents()、および writeContents() メソッドを提供します。isPresent() は、パスで指定されたファイルがディスク上に実際に存在する場合には true を返します。getContents() はファイルの内容を返します。最後の writeContents() は、ファイルの内容を標準出力に書き込むために呼び出されるメソッドで、PHP の fpassthru() 関数を呼び出すことによってコンテンツを書き込みます。
fpassthru の呼び出しは、システムの重要な要素です。XSLT パイプラインの最終結果が計算されると、フレームワークは結果をキャッシュに入れて保管することで、その結果を素早く提供できるようにします。fpassthru() は、この素早い提供を実現するために呼び出されるメソッドです。このメソッドの呼び出しによって、Web サーバーはキャッシュされたファイルの内容を直接標準出力に書き込み、それがユーザーのブラウザーに表示されます。
キャッシュ・ファイルの表現
このキャッシングの振る舞いはシステムの重要な概念であるため、キャッシュに入れられた変換結果を表す ButterflyCache クラスを作成するのは当然のことです (リスト 5 を参照)。
リスト 5. ButterflyCache クラスの作成
class ButterflyCache extends ButterflyFile {
public function __construct($filepath) {
parent::__construct ($filepath);
}
}
|
ButterflyCache はただ単に ButterflyFile を継承するだけなので、このクラスの存在理由を疑問に思うのは仕方のないことです。このクラスが存在する目的は、Butterfly システムにおけるファイルの特殊な機能を表すことに他なりません。この表現により、キャッシュ内のファイルを中心とした抽象化層が提供されます。Butterfly でキャッシュに入れられたファイルに追加の振る舞いが必要になった場合や、別のファイルを後でキャッシュに入れる場合 (例えば、データベースでの結果をキャッシュに入れる場合など)、フレームワークの残りのクラスがそれを認識する必要はありません。キャッシュ・オブジェクトを作成するコードだけが新しい類のキャッシュを把握していればよいだけの話となります。コードの呼び出しはコンパイル時のキャッシュ・オブジェクトの型に大きく左右されることから、このような抽象化は Java やその他の強い型付けの言語には特に役立ちます。PHP のような言語の場合には、このようなクラスを組み込むことは、すべての開発者に対して、後でフレームワークを継承するという目的をより明確にするという意味合いがあります。ButterflyFile だけでなく、ButterflyCache も作成するコードは明らかに、変換結果の内容をキャッシングするためのファイルを作成していることになるからです。
ButterflyXmlDocument の具象実装
一方、ButterflyXmlFile クラスはプレーン・ファイルの概念と機能に対し、概念と多少の機能の両方を追加します (リスト 6 を参照)。
リスト 6. ButterflyXmlFile クラス
class ButterflyXmlFile extends ButterflyFile implements
ButterflyXmlDocument {
public static function create ($filepath) {
return new ButterflyXmlFile ($filepath);
}
public function __construct($filepath) {
parent::__construct ($filepath);
}
public function getDom() {
$dom = DOMDocument::load($this->getFilepath());
if (! $dom) {
throw new Exception ("Couldn't load DOM object from filepath " .
$this->getFilepath());
}
return $dom;
}
}
|
ButterflyCache クラスと ButterflyXmlFile クラスはどちらもディスク上のファイルを表すため、両方とも ButterflyFile を継承します。しかし、ButterflyXmlFile クラスはさらに ButterflyXmlDocument インターフェースを実装することから、その文書の内容を DOMDocument として返す getDom() メソッドを実装します。このメソッドの実装が不可欠なわけは、ButterflyTransformer クラスで使用される PHP の XSLTProcessor オブジェクトは、XML を DOMDocument オブジェクトとしてしか扱わないためです。このクラスはまた、基本 ButterflyFile クラスに定義されている ButterflyXmlDocument の getContents() メソッドと writeContents() メソッドも暗黙的に実装します。
このシステムにあるもう 1 つの XML ソースのタイプは、プレーン XML ストリングです。この特殊なストリングはシステム内で特別な意味と振る舞いを持つことから、ButterflyXmlString クラスにカプセル化されます (リスト 7 を参照)。
リスト 7. ButterflyXmlString クラス
class ButterflyXmlString implements ButterflyXmlDocument {
protected $xml;
public function __construct($xmlString) {
$this->xml = $xmlString;
}
public function getDom() {
return DOMDocument::load($this->xml);
}
public function getContents() {
return $this->xml;
}
public function writeContents() {
echo ($this->xml);
}
}
|
リスト 7 の ButterflyXmlString は XML ストリングをラップし、ラップした XML ストリングに対して ButterflyXmlDocument インターフェースを実装します。getContents() がストリングを返し、writeContents() がストリングを標準出力 (つまり、ブラウザー) にエコー出力します。getDom() がストリングの XML コンテンツを表す DOMDocument を返すと、XSLTProcessor はこのオブジェクトを XSLT スタイルシート、または変換対象のソースである XML 文書として使用できるようになります。
さらなる継承を可能にするためのクラスの抽象化の使用
オブジェクト指向フレームワークの設計で鍵となるのは、クラスを主要な抽象化手段として使用することです。Butterfly クラスに XML ソースがストリングとファイルのどちらであるかを判断する多数の if 文を含め、その結果に応じて動作させることも可能ですが、そのようなコードには全く柔軟性がなく、継承する余地がありません。ButterflyXmlDocument をインターフェースとして抽象化することにより、既存のコードを変更することなく将来継承することが可能になります。例えば、SQL 文を使用して結果を XML に変換する ButterflyXmlSqlSource クラスを作成する場合、ButterflyXmlSqlSource を作成したら、このクラスを ButterflyXmlFile やButterflyXmlString としてではなく、XML のソース・オブジェクトとしてButterfly に渡すことで、システムにこのクラスを追加します。
オブジェクトの作成を単純化するためのファクトリー・クラスの使用
次は、Butterfly システムが XSLT スタイルシート変換のチェーンを適用し、変換チェーンの各ポイント (各 Butterfly オブジェクトが 1 つの XSLT 変換を表現) でキャッシング・メカニズムを提供するようにします。ここで問題となるのは、エンド開発者にとって、Butterfly オブジェクトの作成方法が明確になっていないことです (開発者は関連するそれぞれのクラス、そして各クラスをインスタンス化する方法を理解していなければなりません)。しかも、その方法を明確にするとなると厄介で、開発者が XSLT 変換のチェーンごとに特定のコードを作成したり、あるいは Butterfly のチェーンをアセンブルするコードを作成したりする必要が生じる可能性があります。
このような問題に対するオブジェクト指向のソリューションは、ファクトリー・クラスです。ファクトリー・クラスの目的は、一般には入力基準に応じて他のオブジェクトを作成することですが、Butterfly のファクトリー・クラスである ButterflyFactory の場合は、リスト 8 に記載するような構成ファイルから Butterfly チェーンをアセンブルします。
リスト 8. Butterfly 構成ファイルの例
<butterfly-config>
<chain>
<name>resume</name>
<source type="ButterflyXmlFile">
<arg>resume.xml</arg>
</source>
<xslt file="resume-restructured.xsl"/>
<xslt file="resume-restructured-to-view.xsl"/>
<xslt file="resume-view-to-html.xsl"/>
</chain>
</butterfly-config>
|
この構成ファイルが、Butterfly 変換チェーンを定義します。それぞれのチェーンには、まずソースが記述され、その後に適用する XSLT スタイルシートが任意の数、記述されます。この例で作成しているチェーンは 1 つで、このチェーンでは履歴書の XML 文書、resume.xml を 3 つのスタイルシート変換のシーケンスによって HTML ページにレンダリングします。フレームワークを使用する目的は作業を簡単なものにすることなので、構成を複雑にしてこの目的を台無しにしないように、構成は最小限にしてあります。
ButterflyFactory クラスはこの構成ファイル・フォーマットを読み取って、Butterfly オブジェクトのファクトリーとして動作します (リスト 9 を参照)。
リスト 9. ButterflyFactory
class ButterflyFactory {
private $cacheDir;
private $chains;
public function __construct ($configFile, $cacheDir) {
$this->cacheDir = $cacheDir;
$config = simplexml_load_file($configFile);
$this->chains = $this->mapChainsByName
(is_array($config->chain) ? $config->chain : array($config->chain));
}
protected function mapChainsByName ($chains) {
$byName = array();
foreach ($chains as $chain) {
$name = (string) $chain->name;
if (isset($byName[$name])) {
throw new Exception ("Two Butterfly chains defined with the same
name: $name");
}
$byName[$name] = $chain;
}
return $byName;
}
protected function getChainByName ($name) {
if (! isset($this->chains[$name])) {
throw new Exception ("ButterflyFactory: no chain with specified
name: $name");
}
return $this->chains[$name];
}
protected function createCacheFactory ($cacheDir) {
return new ButterflyCacheFactory ($cacheDir);
}
protected function createButterflyObject ($transformer, $xmlDoc, $cache) {
return new Butterfly ($transformer, $xmlDoc, $cache);
}
public function createButterfly ($xsltFilepath, $xmlDoc, $cache) {
return $this->createButterflyObject
($this->createTransformerFromFilepath ($xsltFilepath), $xmlDoc,
$cache);
}
protected function createTransformerFromFilepath ($xsltFilepath) {
return new ButterflyTransformer (new ButterflyXmlFile($xsltFilepath));
}
public function getButterfly ($chainName) {
$chain = $this->getChainByName ($chainName);
$source = $this->createChainSource ($chain);
$invalidateCache = false;
for ($i = 0; $i < count($chain->xslt); $i++) {
$xslt = $chain->xslt[$i];
$cache = $this->createButterflyCache
($this->createCacheFilename ((string) $chain->name, $i));
if ($invalidateCache && $cache->isPresent()) {
$cache->delete();
}
$source = $this->createButterfly ((string) $xslt['file'], $source,
$cache);
$invalidateCache = $invalidateCache || ! $cache->isPresent();
}
return $source;
}
protected function createChainSource ($chain) {
if (! isset($chain->source)) {
throw new Exception ("Butterfly chain has no source element:
$chainName");
}
$args = is_array($chain->source->arg)
? $chain->source->arg
: array($chain->source->arg);
$argsAsStrings = array();
foreach ($args as $arg) {
$argsAsStrings[] = (string) $arg;
}
return $this->createSourceFromType ((string) $chain->source['type'],
$argsAsStrings);
}
protected function createCacheFilename ($chainName, $xsltNumber) {
return $this->cacheDir . '/' . $chainName . '_' . $xsltNumber .
'.cache';
}
protected function createSourceFromType ($type, $args) {
return call_user_func_array (array($type, 'create'), $args);
}
protected function createButterflyCache ($cacheFilePath) {
return new ButterflyCache ($cacheFilePath);
}
}
|
ButterflyFactory は、構成ファイルのパスとキャッシュ・ディレクトリー (キャッシュされたすべての XSLT 変換を保持するディレクトリー) のパスから作成されます。このファクトリー・クラスは SimpleXML モジュールを使用して XML 構成ファイルを読み取り、構文解析を行って PHP オブジェクトにします。次に連想配列を作成し、定義された各チェーンをその名前にマッッピングして検索しやすくします。
ButterflyFactory の中心的メソッドは getButterfly() です。このメソッドは定義されたチェーンの名前を引数に取り、ButterflyXmlDocument を返します。返されたこのオブジェクトが、チェーン定義の性質によって Butterfly オブジェクトとなり、変換結果を返します。getButterfly() はまず、指定された名前 (例えば、この構成例の履歴書チェーンの場合には “resume”) を基準にチェーンを検索し、ソースである XML 文書オブジェクト (ButterflyXmlFile、または他の ButterflyXmlDocument 実装のいずれか) を定義する <source> 要素がチェーンに含まれていることを確認します。この <source> 要素の type 属性が、ソース文書オブジェクトとしてインスタンス化するクラスを指定します。「resume」チェーンの場合、ソースは ButterflyXmlFile です。
getButterfly() はソース・オブジェクトを取得すると、<chain> に定義された <xslt> 要素をループして、各要素から Butterfly オブジェクトを作成します。Butterfly はそのソース・オブジェクトを引数の 1 つとして取るため、最初の Butterfly オブジェクトにはチェーンの <source> 要素から作成されたソース・オブジェクトが指定されますが、Butterfly オブジェクト自体は $source 変数に割り当られ、ループで次に作成される Butterfly のソース・オブジェクトとなります。このループ処理は、最後のオブジェクトが結果を取得するために呼び出される Butterfly として返されるまで繰り返されます。Butterfly のチェーンはこのようにして作成されるため、返された Butterfly オブジェクトを呼び出すと、そのソースとなっているオブジェクト (おそらく Butterfly) が呼び出され、そのオブジェクトがそのまたソースのオブジェクトを呼び出すといった具合になり、最終的に実際のソース・オブジェクトが呼び出された時点で、そのオブジェクトの内容が呼び出し側の Butterfly に返されます。すると、呼び出し側 Butterfly はその XSLT スタイルシートを適用して結果をそのオブジェクトを呼び出したオブジェクトに返し、結果を返されたオブジェクトも同じことを繰り返すという動作が、チェーンの先頭が変換結果を返すまで、または標準出力に変換結果を書き込むまで続きます。
また、このループは $invalidateCache フラグを最新状態に保つことから、いずれかの Butterfly のキャッシュが削除されると、チェーン内でその上位にあるすべての Butterfly オブジェクトのキャッシュも削除されます。そのため、キャッシュ・ファイルが変換チェーンの任意のステップで削除されると、すべての従属 Butterfly キャッシュ・ファイルが無効になり、キャッシュ・ファイルが再作成されることになります。
次のステップ
これで、XSLT スタイルシート変換機構を適切に処理するフレームワークが完成しました。このフレームワークには、XSLT チェーンの作成や、HTML ページをレンダリングする際の XSLT 変換によるパフォーマンスの影響を排除するためのキャッシュ・ファイルの使用も盛り込まれています。フレームワークを設計する上で次のステップとなるのは、より高度なキャッシュ管理インターフェースを提供すること (現時点では、該当するキャッシュ・ファイルをユーザーが削除しなければなりません)、そしてSQL クエリーの結果を取得するような他の XML ソースを提供することです。リレーショナル SQL の結果を階層型 XML 文書に変換するために OR マッピングの指定が必要になるような構成では、ButterflyXmlSqlSource などのクラス自体を軽量のフレームワークにすることも可能です。他の可能性としては、キャッシュ・ファイルに SQL データベースを使用する方法も考えられますが、パフォーマンスに関して言えば、ディスク・アクセスと fpassthru() を使用するのが最善のソリューションであることに変わりはありません。
まとめ
Butterfly フレームワークは、PHP 5 で XSLT を簡単に使用できるようにして、スタイルシート・チェーンとキャッシングによるパフォーマンスの向上を実現する手軽な方法です。フレームワークとしては至ってシンプルでわかりやすい Butterfly ですが、そんな単純なフレームワークが、XSLT スタイルシートを適用する仕組みを PHP コードから切り離し、開発者が作業の核心、つまり XSLT 自体に専念できるようにします。この Butterfly についてさらに詳しく調べてみてください (「参考文献」を参照)。
参考文献 学ぶために
製品や技術を入手するために
議論するために
著者について  | 
|  | Jake Miles は、ビジネスを対象としたあらゆるビデオ Web ソリューションを提供する新しい会社、Twistage, Inc. で Senior Technical Liaison を務めています。さまざまな言語とソフトウェア技術に経験を持ち、10 年間、プロの開発者として働いてきた彼は、子供のころから熱心な生徒で、10 歳のときからソフトウェアをいじり回していました。またボランティアで教師も務め、誰でもわかりやすく教えられれば何事も習得できると信じています。 |
記事の評価
|