エッ indextermでループ!?

今回は失敗談です.
もうDITAを導入して3年になるお客様がいます.当初はDITA Open Toolkit 1.4.21の時代でした.その後1.5.1にアップしたのでスタイルシートもXSLT2.0に書き直してあります.そのお客様から突然連絡がありました.PDFのビルドが1時間たっても終了しないというのです.データとログをいただいたのですが、確かにログはスタイルシートがエラーメッセージを山ほど出して途切れています.どうやら無限ループしてしまったようです.エラーメッセージを見ると、なんと全topicに対して出ているのですが、「テキストのないindextermがある.これを無視する.」というものでした.エッ?と思ってtopicを見るとそこには次のようなindextermが記述されていました.
 
<prolog>
  <metadata>
    <keywords>
      <indexterm>
        <index-sort-as/>
      </indexterm>
    </keywords>
  </metadata>
</prolog>
 
どうもお客様の方では新規のtopicを作成する場合のオーサリングツールのテンプレートを変更したらしく、上記のindextermはすべてのtopicにあります.つまり全部空のindextermです.
 
スタイルシートはindextermにテキストがないのは無効なのでエラーメッセージを出していましたが、さすがに処理はそこまでで、索引ページでindextermをソーティングするときにこの条件までチェックしていませんでした.
 
一般にXSL-FOへの変換ではindextermは出現した位置に、<fo:wrapper index-key="..."/>("..."は<indeterm>のテキストから作ったキー)を生成し、backmatter/booklists/indexlistがあると、そこでindextermをソーティングして、<fo:index-page-citation-list>でFormatterに索引ページを生成させます.
 
しかしindextermのソーティングでは、対象のindextermがすべてテキストなしなので、さすがにループしてしまったようです.ソーティングの前にテキストがないindextermは除外するコードを3ステップつけてやったら5分もかからず一発でビルドは終了しました.
 
まあシステムを3年も運用しているといろいろトラブルはあるものですが、スタイルシートが安定すると今度はこのようなデータパターンに依存した障害が発生するようになります.
 
お客様の立場からすると、topicを作るときあとからいちいち入力するのを省いて<indexterm>のプロトタイプを作ってしまおうという考え方なのでしょう.これは一理あります.しかしスタイルシートは、indextermにテキストがないのがオーサリングミスか、それともプロトタイプだからOKか?という判断はできません.しかし今回の場合エラーメッセージを出していたので問題を解く鍵がすぐわかりました.
 
ちなみにDITA-OT 1.5.4のFO Plug-inでやってみるとエラーも何も出ないのですが、不正なFOを作ってPDFも0バイトという結果に終わります.もしこんな結果だったらお客様は何がなんだかさっぱりわからないでしょう.エラーメッセージはもっと積極的に出すべきだと思いますが、FO Plug-inはほとんどエラーを出しません.これではリファレンスインプリメンテーションとは言えないでしょう.
 
さて今回のエラーからいろいろ教訓を得ました.まずこのようなデータが来るとはシステム設計時にはとてもじゃありませんが想定できなかったでしょう.しかし、やはり何らかのエラーが出たとき、プログラム(スタイルシート)がそれをとく鍵をログに出しておくことは非常に重要だということです.私の作ったスタイルシートは論理エラーを含め、山ほどのメッセージが定義されており、これはすべてユーザーズマニュアルに書いています.作るときは非常に手間に思ったものですが、作るときより運用する期間の方が長いのですから、相対的に見るとしておいた努力は無駄にはならなかったと考えています.