目次


ヒント: XSLTスタイル・シートからJavaScriptを呼び出す

スタイル・シートに機能性を追加する

Comments

このヒントでは、Apache ProjectのXalan Java 2変換エンジンとそのインプリメンテーションを使用します (参考文献を参照)。全体的な概念はどのインプリメンテーションでも同じですが、XSLT勧告は特定のインプリメンテーション方式を必須とはしていません。Xalanのほかに、JavaScriptのインプリメンテーションの入っているjs.jarファイル (参考文献を参照) がCLASSPATH 上に必要であり、Xalanディストリビューションの一部であるbsf.jar も必要です。

ソース文書

サンプル・ソース文書は、数当てゲームのエントリーを記録したものです。このゲームでは、プレイヤーが1~100の数字の推定値を3つ提出します。スタイル・シートは、これら3つの推定値を取り込み、ランダムな数 (答え) と比較します。サンプル文書には、次の2組の推定値が含まれています。

サンプル文書
<?xml version="1.0"?>
<entries gameID="DWO">
<entry>
<player>John</player>
<guess>3</guess>
<guess>9</guess>
<guess>222</guess>
</entry>
<entry>
<player>Mary</player>
<guess>88</guess>
<guess>76</guess>
<guess>5</guess>
</entry>
</entries>

コンポーネントの作成

拡張要素または拡張関数を使用するにあたっての最初のステップは、実行するコードを定義することです。これには、新しい名前空間と、コードのコンテナーを定義することが含まれます。

基本的なスタイル・シート
<?xml version="1.0"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:lxslt="http://xml.apache.org/xslt"
xmlns:result="http://www.example.com/results"
extension-element-prefixes="result"
version="1.0">

  <lxslt:component prefix="result" elements="rules" functions="getResult">
<lxslt:script lang="javascript">
function getResult (thisGuess) {
var thisResult = parseInt(Math.random()*100);
if (thisResult == parseInt(thisGuess)) {
return "Correct!";
} else {
return "Wrong! The actual answer was "+thisResult+
                         ", not "+thisGuess+".";
}
}
    </lxslt:script>
</lxslt:component>

<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>

一見すると、これは典型的なスタイル・シートに、2つの新しい名前空間を追加しただけのものに見えます。第一に、接頭部lxslt により、どの要素が新しい機能を定義しているかをプロセッサーに伝えます。第二に、result は、その新しい機能の呼び出しを示します。最後に、extension-element-prefixes 属性は、通常の流れの一部として変換してはならない要素をプロセッサーに伝えます。(それでも、このあと見るとおり、出力するべき値を返すことはできます。)

component要素そのものでは、その内側のコードすべてがresult 名前空間接頭部から呼び出されることを指定します。さらに、どの関数が拡張要素から呼び出され、どの関数が拡張関数から呼び出されるかも、プロセッサーに対して指定します。script要素では、関数そのものを記述します。

この例では、引数を取り、1~100のランダムな数とその引数を比較して、結果を示す文字列を返す関数を、まず記述します。

拡張関数

拡張関数は、XSLTスタイル・シートにおいて実質的にXPathを拡張するものであり、translate()round() などの組み込み関数と同じように使用できます。

関数を呼び出す
...
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>

<xsl:template match="entry">
Guesser: <xsl:value-of select="player"/>
<xsl:apply-templates select="guess"/>  
</xsl:template>

<xsl:template match="guess">
Guess: <xsl:value-of select="."/> 
Actual: <xsl:value-of select="result:getResult(string(.))"/>
</xsl:template>
</xsl:stylesheet>

この例では、現在のノード (guess) の文字列値をgetResult() 関数に渡します。名前空間により、プロセッサーは、resultコンポーネント内の関数をトリガーするべきことを知ります。

図1. 最初の結果
図1. 最初の結果
図1. 最初の結果

要素の使用

拡張要素は、拡張関数よりも少し複雑です。拡張要素は、単に値を返すというだけではなく (もちろん、値を返すこともできるが)、スタイル・シートの処理における特定の「時点」で特定のアクションを実行することを意図しています。さらに、拡張関数のように引数の任意のリストを取るのではなく、拡張要素の背後にあるコードは、明確に定義された2つの引数を取ります。

rules 要素は、rules() 関数の処理をトリガーします。この関数は、その引数の1つとしてrules 要素そのものを取るため (elem)、その要素に関連付けられている任意のカスタム属性の値を取得できます。

プロセッサー・コンテキストの使用

おそらく、拡張要素の最も強力な機能は、XSLプロセッサー・コンテキスト引数によってソース文書そのものにアクセスできる機能でしょう。

プロセッサー・コンテキスト
...
<lxslt:component prefix="result" elements="rules" functions="getResult">
<lxslt:script lang="javascript">
...
function rules(ctx, elem) {
       ctxNode = ctx.getContextNode();
gameID = ctxNode.getFirstChild().getAttribute("gameID");
return "Contest "+gameID+" is based on "+
elem.getAttribute("guessType")+" guesses.";
}

</lxslt:script>
</lxslt:component>

rules 関数の最初の引数がプロセッサー・コンテキストであり、org.apache.xalan.extensions.XSLProcessorContext オブジェクトの形式です。この引数を利用すると、スタイル・シート、および変換プログラムが、現在変換を実行しているコンテキスト・ノード (そのソース・ツリー全体) を表すオブジェクトを取得できます。コンテキスト・ノードにアクセスすることは、最も一般的な操作です。getContextNode() メソッドから返されるノードは、典型的なXMLノードであり、標準的なDOM操作を適用できます。

図2. 最終的な出力
図2
図2

ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=XML
ArticleID=242727
ArticleTitle=ヒント: XSLTスタイル・シートからJavaScriptを呼び出す
publish-date=04012002