今のDITA-OTではXSLTプロセッサはSaxon-B 9.1というXSLT2.0プロセッサが標準になっています.昔はSaxon 6.5やXalan 2.7.1というXSLT 1.0のプロセッサが標準でした.最新のSaxonは9.5なのでもうちょっと古いバージョンになります.何故このバージョンになっているかというと、次のSaxon9.2からHE(Home Edition)とPE(Prpfessional Edition)/EE(Enterprise Edition)と分かれてしまい、オープンソースのHEバージョンではスタイルシートからJavaの拡張ライブラリが呼べなくなってしまったからです.DITA-OTではJavaのライブラリ呼び出しを使っています.こういう仕組みを無償で使えるSaxonは9.1が最後のためだからです.oXygenなどのXMLエディタではたいてい最新のSaxon EEがついてくるので、oXygenを使っている限りはXSLT3.0でスタイルシートを書くことだって可能です.もちろんSaxon PE/EEを買ってDITA-OTに組み込めば使えるXSLTの機能はずっとアップします.
ところでこのSaxonをantのbuild.xmlから呼び出すには2つのやり方があります.
2.javaタスクを用いる、つまりSaxonのメインクラスのnet.sf.saxon.Transformを指定してSaxonを呼び出す.
私は従来は2.を使用していました.理由はスタイルシートで次のようにsyspropertyを使用したいのですが、
<param name="PRM_OUTPUT_DRAFT_COMMENT" expression="${output.draft.comment}" if="output.draft.comment"/>
と条件付(output.draft.commentプロパティが定義されていた場合のみ)パラメータでプロパティを渡すことができます.でもjavaタスクではこのようなことはできず、
<arg line='"PRM_OUTPUT_DRAFT_COMMENT=${output.draft.comment}"'/>
とパラメータをハードコードしなければ書かねばなりません.このコマンドラインには癖があって、"="の右側が空だとエラーになってしまいます.つまりパラメータは必ず値を書かねばなりません.これは結構重要な問題で、もしパラメータが定義されていない場合に備えて、
<property name="output.draft.comment" value="no"/>
などと初期値をbuild.xmlに指定することが必要になってきます.でももし当該のプラグインが業務でCMSのアプリケーションからお客様が起動するようになった場合、パラメータの初期値は下手をすると以下の3箇所にバラバラに存在してしまう結果になります.
(A) DITA-OTを起動するCMSのアプリケーション
CMSとインテグレーションする場合たいていトラブルが発生します.パラメータが渡されていないためプラグインの動作結果が意図通りにならない場合もあります.なので私は2.のbuild.xmlに初期値を持つことは極力やめて、CMSのアプリケーションからすべてのパラメータをもらった方が良いと考えています.そうしないとパラメータの値がどこでどう設定されるのかで、本番環境に組み込んだときに大変な思いをすること間違いないからです.
<xsl:param name="PRM_RESOURCE_FILE" as="xs:string" required="yes"/>
<xsl:variable name="pResourceFile" as="xs:string">
<xsl:choose>
<xsl:when test="doc-available($PRM_RESOURCE_FILE)">
<xsl:sequence select="$PRM_RESOURCE_FILE"/>
</xsl:when>
<xsl:otherwise>
<xsl:message select="concat('$PRM_RESOURCE_FILE=',$PRM_RESOURCE_FILE,' がありません!')"/>
<xsl:sequence select="''"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
でもJAXPでこのコードを動かすとdoc-available()はfalse()を返し、ファイルにアクセスすることができません.JAXPでは先頭に"file:/"をつけてちゃんとしたURIにしてやる必要があるようです.例えば次のようにコードを変えます.これはjavaでもxsltタスクでも動きます.
<xsl:param name="PRM_RESOURCE_FILE" as="xs:string" required="yes"/>
<xsl:variable name="pResourceFile" as="xs:string">
<xsl:variable name="tempResourceFile" as="xs:string">
<xsl:choose>
<xsl:when test="starts-with($PRM_RESOURCE_FILE,'file:/')">
<xsl:sequence select="$PRM_RESOURCE_FILE"/>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="concat('file:/',$PRM_RESOURCE_FILE)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:when test="doc-available($tempResourceFile)">
<xsl:sequence select="$tempResourceFile"/>
</xsl:when>
<xsl:otherwise>
<xsl:message select="concat('$PRM_RESOURCE_FILE=',$PRM_RESOURCE_FILE,' がありません!')"/>
<xsl:sequence select="''"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
次はデバッグ方法の違いについて紹介します.