Entry

XML::Sablotron を使ってみた

2006年03月28日

以前作ったひねくれ XSLT CGI を,いい加減 Perl で実装した方がよさそうだ(C で書いたからひねくれているというだけなんだけれど),ということで,XML::Sablotron をぼちぼちいぢりはじめました。なんで XML::LibXSLT を使わないのかというと,このサーバに入ってないからです。XML::Sablotron は入ってました。

Sablotron は,Expat ライブラリを元に C で実装した XSLT プロセッサです。Java 関係のプロセッサを除けば,XSLT プロセッサの中でも割と古参の部類に入るんじゃないでしょうか。パフォーマンスは libxslt の方が上だと聞いたけれど,本当かどうかは知りません。

ここでは,テストしたスクリプトを紹介しがてら,使い方をメモしておきます。

とりあえず,あれこれとうんちくをたれるのもアレなんで,テストしたスクリプトの全体図を以下に示します。del.icio.us からあたしのブックマーク(RSS)を取ってきて,ローカルにあるスタイルシート(rss.xsl)に食べさせる,というスクリプトです。エラー処理がなおざりなんですけれど,大目に見てください。

use strict;
use LWP::Simple;
use XML::Sablotron qw (:all);

my $sab = new XML::Sablotron;
my $sit = new XML::Sablotron::Situation;

my $template_url = 'file://rss.xsl';
my $data_url     = 'http://del.icio.us/rss/aian/';

## del.icio.us から RSS をもらってくる
my $data_content = LWP::Simple::get($data_url);
$sab->addArg($sit, 'input', $data_content);

## XSLT 変換
$sab->process($sit, $template_url, 'arg:/input', 'arg:/output');

## 結果を取り出す
my $result = $sab->getResultArg('arg:/output');
print $result;

## あとしまつ
$sab->freeResultArgs();
undef $sab;
undef $sit;

手順は次の4つのステップを踏めばOKです。

  1. XML::Sablotron オブジェクトと XML::Sablotron::Situation オブジェクトを作る
  2. 変換元 XML の URL とスタイルシートの URL,それと出力先の URL (場合によってはパラメータの URL)をそれぞれ決める。
  3. XSLT 変換
  4. あとしまつ

順に説明します。

まず,XML::Sablotron を使うには,XML::Sablotron オブジェクトと XML::Sablotron::Situation オブジェクトを作らなくちゃいけません。たとえて言うなら,XML::Sablotron オブジェクトが実際に XSLT 変換をする工場で,XML::Sablotron::Situation オブジェクトが必要な材料を詰め込む場所といったところです。これは単に new すればいいだけなので簡単です。

my $sab = new XML::Sablotron;
my $sit = new XML::Sablotron::Situation;

次に,XSLT 変換の材料を仕込みます。材料を仕込むというのは,XML::Sablotron がアクセスできる URL を用意するということです。

この例ではリモートにある XML 文書と,ローカルにあるスタイルシートを扱っていて,URL スキームは,それぞれ「http:」と「file:」になります。もっとも,ここが面倒なんですけれど,XML::Sablotron は,(今のところ)「file:」と「arg:」の2種類の URL スキームしかサポートしていないんですね。というわけで,この例の場合,手元のスタイルシート(rss.xsl)には「file:」スキームで直接アクセスできるけれども,変換元(del.icio.us の RSS)の文書は「http:」スキームを使って指定しているので,そのままではアクセスできません。

しかたがないので,ここでは,まずリモートの XML 文書を HTTP 経由で変数($data_contents)に取り込んで,この変数に「arg:」スキームを使ってアクセスすることにします(というかこれが常道)。ここで,「arg:」スキームってなんじゃらほい,という方もいらっしゃるかもしれませんけど,「変数に入った文字列にアクセスするためのスキーム」だと思ってもらっていいと思います。ここでは,LWP::Simple モジュールを使って変換元文書を $data_content に読み込んでいます(LWP モジュールについては本題から逸れるので割愛)。

変数に無事読み込めたら,あとはこれを「arg:」スキームの URL に紐付ければいいだけです。紐付けするには,XML::Sablotron のインスタンス・メソッドである addArg() を使います。

$sab->addArg($sit, 'input', $data_content);

引数は順番に「XML::Sablotron::Situation オブジェクト」,「URL」,「URL に指される変数」です。ここでは,「arg:/input」という URL を付けました(スキーム名はいらない)。名前は適当で構いません。

さて,URL も決まったということで,ここからは楽ちんです。あとは XML::Sablotron オブジェクトのインスタンス・メソッドである process() に変換してもらいます。

## XSLT 変換
$sab->process($sit, $template_url, 'arg:/input', 'arg:/output');

引数は順番に,「XML::Sablotron::Situation オブジェクト」,「スタイルシートの URL」,「変換元 XML 文書の URL」,「変換結果を保持するバッファの URL」です。最後の引数がハテナかもしれませんけど,変換結果を受けとめる器(バッファ)の名前(URL)だと思ってください。この名前も適当で構いません。ここでは「arg:/output」にしました。変換結果は getResultArg() メソッドを使って取り出します。引数に「変換結果の URL」を指定すると,変換した文書をスカラー値で返します。

## 結果を取り出す
my $result = $sab->getResultArg('arg:/output');
print $result;

最後に後始末をしてオシマイです。これは特に気にすることもないのかもしれないけれど,大きな文書を扱う場合でスクリプトが長い間動いているような場合は,適宜 free しないとメモリを無駄使いすることになってしまいます。

## あとしまつ
$sab->freeResultArgs();
undef $sab;
undef $sit;

……と,小さいスクリプトなのに長々と講釈をたれてしまいました。XSLT で作るスタイルシートを考えてみると,http: スキームが使えないのはかなりイタイものの(document() 関数が変換スクリプトとくっついてしまう),それなりにコンパクトに実装できることから,使い出はあるんじゃないかと思います。

少なくとも,C で書くよりはずっと楽。

Trackback
Trackback URL:
Ads
About
Search This Site
Ads
Categories
Recent Entries
Log Archive
Syndicate This Site
Info.
クリエイティブ・コモンズ・ライセンス
Movable Type 3.36
Valid XHTML 1.1!
Valid CSS!
ブログタイムズ

© 2003-2012 AIAN