DITA-OTのカスタマイズ(2)

DITA-OTの拡張ポイントの定義には大きな問題があると書きましたが、それは次のようなものと考えています.

「DITA-OTの動作を自分(プラグイン)の「都合」で変えるのだから、他のプラグインに絶対迷惑をかけてはならない!」

これと同じような例がプラグインbuild.xmlへの登録を担うintegrator.xmlにもあります.integrator.xmlは、DITA-OTのメインのビルドファイルに、自分(プラグイン)への制御の移行を組み込むものです.以前複数の会社で別々のプラグインを作り、お客様に納品する仕事をしていたことがありましたが、単独環境では動くのに、他社のプラグインを入れると参照している画像がすべて見つからなくなり、PDF出力のプラグインがエラー終了するという問題がありました.よくよく調べた結果、他社のHTMLのプラグインのintegrator.xmlが問題でした.自分の都合で、すべての画像ファイルをoutフォルダにコピーするプロパティ設定をしていたのです.HTMLでは必要でも、このような機能はPDFでは不要です.結局他社のプラグインのintegrator.xmlを直してもらったことがありました.

ましてやDITA-OTの動作を変える拡張ポイントの定義ですから他に迷惑をかけないよう、非常にうまくやる必要があります.ではそれはどのように行われているのでしょうか?参考に、あらかじめ組み込まれている、<xsl:import href="../../plugins/org.dita.specialization.eclipsemap/xsl/mapref-plugin.xsl"/> を見てみます.すると次のようなコーディングがあります.

  <xsl:param name="TRANSTYPE"/>

  <xsl:template match="/">
    <xsl:choose>
      <xsl:when test="contains($TRANSTYPE,'eclipse') and *[contains(@class,' eclipsemap/plugin ')]">
        <xsl:apply-templates mode="createPlugin"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:apply-templates/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

つまり、mapref.xslには$TRANSTYPE(DITA-OTで指定する-Dtranstypeの値)があって、これがパラメータで渡されるようであることがわかります.このeclipse.mapのプラグインでは、transtypeが自身であればmode="createPlugin"で自分に必要な処理をする、そうでなければ既定の処理をするという礼儀をわきまえたコーディングをやっていることがわかります.なるほどです.まあこれがDITA-OT 1.8.5 + XSLT 1.0でできる限りのコーディングなのでしょう.

このように書いたのは、拡張ポイントがxsl:importという機能を使用しているからです.このコードは../../plugins/org.dita.specialization.eclipsemap/xsl/mapref-plugin.xslにありますが、もしこれより後でxsl:importするプラグインが同じようなコードを書いたら、XSLTのimport precedenceの規則に従って後者の方が優先されてしまうのです.プラグインがどのような拡張ポイントを定義しているかは、別のプラグインからはわかりません.DITA-OTのintegrator.xmlがxsl:importの順番を決めてくれます.しかしこれとて規則性のあるものではないでしょう.

という訳で、DITA-OT 1.8.x + XSLT 1.0ではこれが限界です.もし処理がバッティングするなら、起動するDITA-OTを目的別に分けるしかありません.ちなみにDITA-OT 2.xでは、[DITA-OT]/xslのスタイルシートXSLT 2.0に書き換えが行われています.ですので上記のプラグインはまだ救いがあります.次のように書けば良いのです.

  <xsl:template match="document-node()[contains($TRANSTYPE,'eclipse') and *[contains(@class,' eclipsemap/plugin ')]]">
     <xsl:apply-templates mode="createPlugin"/>
  </xsl:template>

こうすればまだいけるのではないでしょうか?XSLT 1.0では"["と""]"の中(述語:predicate)の中に、パラメータやグローバル変数への参照は書けませんでした.XSLT2.0ではかけるのです.では実際に最新のDITA-OT 2.3.2でどうなっているか見てみました.するとせっかくXSLT 2.0で書き直していたのにplugins/org.dita.specialization.eclipsemap/xsl/mapref-plugin.xslのコードは変わっていませんでした.これはバグとまでは言いきれませんが、十分コードの質を向上させる余地があります.

ちなみにいろいろえらそうなことを言っていますが、では私のコードはどうやったのでしょう?chapterやpartに特有な属性を参照したditamapの先頭のtopicrefに転記するというのは意外とあってもおかしくありません.以下にアーカイーブして置いておきます.よかったら御参考にしてください.(DITA-OT 1.8.5でしか動作確認はとってありません.もちろん他のプラグインに完璧に影響を及ぼさないようにはできませんし、他のプラグインのテンプレートで無効にされてしまう可能性もないとはいえません.)