タコのDITA-OTのFO Plug-in

DITA-OTとお付き合いが始まったのは2006年くらいです.当時はまだDITA-OTも1.2と古く、標準のPDF出力はIBMの方が作ったものが搭載されていました.この頃ダークホースとして現れたのがIdiom Technologiesが作ったFO-Pluginです.ちょっと格好の良いデザインでPDFを生成するので、組み込んで使った人も多いはずです.現在では、DITA-OTでPDFを出力しようとすると、このPDFプラグインが自動的に動くようになっています.格納場所は[DITA-OT]/fo/demo/foです.従来のIBMスタイルシートは、[DITA-OT]/demo/legacypdfとして名を留めています.
 
FO-Pluginは当初はIDIOMがメンテナンスをしていたのですが、途中から投げ出してしまい現在ではSuite Solutionがメンテナンスしています.では、どのような特徴があるのでしょうか、簡単に紹介します.
 
■ 元からXEP専用に作られていた.
FO-PluginはもともとRender-XのXEP専用に作られていました.
 
 
あたりの古いFO Pluginを落としてみると、README.txtに書いてあるのがわかります.ですからスタイルシートもXEPの拡張機能を使ってあってとても他のFormatterで使用できる環境ではありませんでした.また日本語環境もひどいものでした.(これはPlug-in自体の問題というよりFormatterの問題でもあります.XEPやFOPの日本語フォントの指定が如何に煩わしいか知っている方ならご理解いただけると思います.)
 
■ 特異なスタイルシートバージョン:XSLT1.1
昔のDITA-OTは、Saxon6.5とXalanの2つが使えました.XSLT1.0プロセッサでも動いていたのです.ところが、XEPはSaxon専用に作られていました.XSLT1.0の仕様が199年11月に勧告となったあと、一時期W3CからXSLT1.1のワーキングドラフトがでたことがありました.Saxon6.5はいちはやくこのワーキングドラフトを実装したのですが、FO-PluginはこのXSLTバージョンを使っていります.つまりSaxon6.5だけに実装された機能をXSLT1.0の時代に使っていたのです.あまりこういうことはやるべきではないと思いますが、なんとこのXSLt1.0というスタイルシートバージョンはXSLTプロセッサがSaxonB 9.1になった、現在のDITA-OTでもそのままです.ですから昨日紹介したように、関数を使うときには、
 
<xsl:function version="2.0" name="opentopic-func:getDestinationId">
 
と、vesion属性を2.0にしています.本来XSLT2.0にスタイルシートを書き直せばよいのですが、そんなことをボランティアのSuite Solutionがやっている暇はないのでしょう.ほったらかしになっています.というわけで、このスタイルシートは、XSLT1.1という特異なバージョンを使っているスタイルシートです.XSLT1.1は結局勧告にはいたらずXSLT2.0がその後世にでました.XSLTをちゃんと勉強しようとする人にとって、このXSLT1.1で書かれているFO Plug-inはまったく手本になりません.むしろ見てはいけないスタイルシートだと思います.
 
■ インチキな索引処理
確かに索引を作るのはそう簡単ではないのですが、FO Plug-inはindextermを前処理で独自のネームスペースopentopic-indexの特別な要素に置き換えて楽に処理をしようとしています.うまく動けばまだ良いのですが、当初の実装は、例えば
 
<indexterm><keyword><tm tmtype="reg">Windows</tm></keyword></indexterm>
 
なんというデータを作ると、一発でNPE(Null Pointer Exception)になっていたものでした.現在では、NPEにこそならないものの、このデータは肝心の索引ページにはでてきません.索引の前処理(Javaで実装)でなんのエラーメッセージも出さずに抹殺されます.
なぜ索引の前処理をやるのかというと、Frame Makerの索引からのマイグレーションのために特殊なキーワードをサポートしているからです.これは[DITA-OT]/fo/demo/fo/README.txtにも書いてあります.
 
About the index extensions
==========================
The index generation feature adds extensions to DITA's indexterm that can be
expressed as content of that element. These extensions are expressed in a
FrameMaker-like syntax in the element's textual content, and provide
functionality not yet available in the standard indexterm element. They also
help migration from legacy FrameMaker content. For example, the following
generates a "see also" entry:
 <indexterm>Carp:<$nopage>see also Goldfish</indexterm>
As:
 Carp, 34
    see also Goldfish 
The extended syntax consists of:
 : (colon)       Separates levels in an entry
 ; (semicolon)   Separates entries in a marker
 [] (brackets)   Specifies a special sort order for the entry
 <$startrange>   Indicates the beginning of a page range
 <$endrange>     Indicates the end of a page range
 <$nopage>       Suppresses the page number in the entry (for example, in a See entry)
 <$singlepage>   In a marker that contains several entries, restores the page number for an entry that follows a <$nopage>  building block
DITA 1.1 indexing elements have been implemented in this plugin that
should make these extensions unnecessary. You can now express see/see
also, sort order and page ranges using standard DITA 1.1 elements.
 
しかし、このようなものは、新規にDITAのインスタンスを作ろうという人にとっては、不要で有害でしかありません.この索引の前処理はsourceforgeに何回もバグ報告がされていますが、根本的には直っていません.いや、直せないのでしょう.索引の処理などソーティングを除けばJavaなんか使わずともスタイルシートで十分出来ます.Idiomの索引処理はJavaに組み込まれているがために、かえって初心者からの敷居を高くし、かつメンテナンスが出来ないという矛盾に陥っています.