XSL-FOのデバッグ

XSL-FOのスタイルシートを作っていると、時にしてFOをエディタで開いて中をデバッグしなければならないことがあります.
 
DITAのPDF出力のスタイルシートなんかだったら、あまりXSL-FOを覗くことはないのではと思います.たいてい出力物がページ数が多くて、いったんレイアウト仕様をスタイルシートでちゃんと実装してしまえば、XSL-FOまで見なければならない機会はそうありません.出来たPDFを見て「こんなものかな~?」と検証する感じになります.
 
でも世の中にはそのような世界ではないものもあります.PDFは数ページでも徹底的にきびしいレイアウト仕様に厳格に従って出力しなければならない場合もあります.このような場合はXSL-FOのデバッグが必須作業となります.デバッグといってもXSL-FOのオブジェクトとプロパティの出力結果が意図通りにいっているかを確認し、必要なときはパッチ修正してFormatterで表示を検証し、スタイルシートに結果を戻す作業です.
 
このような時XSL-FOをエディタで開かなければならないのですが、XSL-FOを作るスタイルシートは<xsl:output method="xml" indent="no"/>で作ってあります.何故かと言うと<fo:inline>の中をインデントされてしまっては、インデントしない場合に比べて出力結果が変わってしまうからです.その結果、スタイルシートの開発者は、たいていインデントされていないXSL-FOを見なければならない羽目になります.インデントされていないものは次のようにな出力です.
 
イメージ 1
 
 これをエディタで開いて見るのは非常に苦痛を伴います.ともかくタグとタグがくっついてしまっているので、階層がわかりません.仕方がないので手で編集したりしますがこの作業も結構大変です.しかしエディタで開いて見てすぐに階層がわかるようにするためにスタイルシートを書き直す(例えばfo:blockのあとに&#x000A;を入れるようにする)のはあまり現実的ではありません.そもそもXSL-FOを見ることのためだけに工数をかけてスタイルシートを変更するのは、開発費を払ってくれるお客様にとってはなんの得にもならないからです.
 
ちょうどXSL-FOをデバッグしなければならない仕事に入ってしまって、さてこういう時何かうまくできないか?と考えたのですが、結論はバッチファイルでXSL-FOを作ったら、自動的にそのXSL-FOを入力してインデントしたXSL-FOを同時に自動的に作ってしまうことでした.これならバッチファイルに処理を一個追加しておくだけで済みます.毎回デバッグするわけではないですが、見たいときにすぐこのインデントしたXSL-FOを開きさえすればよいので、この方法は実用的でした.
 
インデントしたXSL-FOを作るコマンドラインは次のようなものです.Saxonを起動します.
 
java net.sf.saxon.Transform -t -xsl:indent_fo.xsl -o:%1_indent.fo -s:%1.fo 2>>err.txt
 
ここで%1は入力XMLファイルのパスの拡張子抜きを指定するバッチファイルのパラメータです.またindent_fo.xslは次のような超簡単なスタイルシートです.
 
[indent_fo.xsl]
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:fo="http://www.w3.org/1999/XSL/Format"
  xmlns:axf="http://www.antennahouse.com/names/XSL/Extensions"
>
  <xsl:output method="xml" indent="yes"/>
  <xsl:template match="*">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>
 
結果はこんな風になります.見やすさは格段に向上しました.
 
イメージ 2
 
 XSL-FOのデバッグというのはそう機会があるわけではないです.でもないからこそ、いざという時こんな工夫で結構デバッグの効率は上がります.