意外と大変なmap参照

同じPDFを作るのにも版下用に作成するのと閲覧用に作成するのは結構要件が異なります.特にいわゆる取扱説明書のように製品に冊子として添付する用途のPDFを作る場合、極力紙を節約するためにページ数をコントロールしたい要望があります.例えばchapterから成るbookmapの場合、次のように@outputclassでfo:page-sequenceをコントロールしたいという話がありました.

<bookmap>
  <mainbooktitle>PDF for printing</mainbookmap>
  <chapter navtitle="Chapter 1" href="chapter-1.ditamap" format="ditamap"/>
  <chapter navtitle="Chapter 2" href="chapter-2.ditamap" format="ditamap" outputclass="auto-even"/>
  <chapter navtitle="Chapter 3" href="chapter-3.ditamap" format="ditamap" outputclass="auto-odd"/>
  <chapter navtitle="Chapter 4" href="chapter-4.ditamap" format="ditamap" outputclass="auto"/>
  <chapter navtitle="Chapter 5" href="chapter-5.ditamap" format="ditamap" outputclass="auto-odd"/>
  <chapter navtitle="Chapter 6" href="chapter-6.ditamap" format="ditamap" outputclass="auto-even"/>
  …
</bookmap>

@outputclassの値は、各章のfo:page-sequence/@initial-page-numberに反映させたい意図です.こうすることにより各章の先頭ページを偶数ページから始めるのか、奇数ページから始めるのかをコントロールできます.

ところがこの方法には大きな落とし穴があります.それは、各chapterはサブマップを参照しているということです.例えばchapter-2.ditamapは次のようなものでしょう.

<map>
  <topicref href="chapter-2-1.dita" format="dita"/>
    <topicref href="chapter-2-2.dita" format="dita"/>
    <topicref href="chapter-2-3.dita" format="dita"/>
    ...
  </topicref>
</map>

一見何の問題もなさそうなのですが、実はchapter/@outputclassはマージ後中間ファイルに残りません.chapter-2-1.ditaを参照するtopicrefは、中間ファイルには例えば次のように展開されます.かろうじて@class属性には元がchapterであった痕跡を残してもらえる程度で@outputclassは出てきません.あくまで参照先のmap/topicrefの属性の有無が採用されます.

<topicref class="- map/topicref bookmap/chapter " 
          format="dita" 
          href="#unique_5" 
          type="topic" 
          xtrc="topicref:1;5:81" 
          xtrf="D:\SVN\samples\20160829-mappull\chapter-2.ditamap" 
          ohref="chapter-2-1.dita" 
          first_topic_id="#unique_5">
   ...
</topicref>

もしoutputclass="auto-even"を残したければサブマップの側に書いてやらなければなりません.

<map>
  <topicref href="chapter-2-1.dita" format="dita" outputclass="auto-even"/>
    <topicref href="chapter-2-2.dita" format="dita"/>
    <topicref href="chapter-2-3.dita" format="dita"/>
    ...
  </topicref>
</map>

でもこれだとサブマップの再利用性が落ちてしまいます.まあギンギンに紙を節約しようとするのですから、あまり他で再利用する意図はないのかもしれませんが.

ではchapter/@outputclassを得るためにはどのようにすれば良いのでしょうか?方法は3つほど考えられます.

① サブマップ参照の方法を変える.
これが一番簡単です.上記の例では

<chapter navtitle="Chapter 2" href="chapter-2-1.dita" format="ditamap" outputclass="auto-even">
  <mapref href="chapter-2.ditamap"/>
</chapter>

[chapter-2.ditamap]
<map>
  <topicref href="chapter-2-2.dita" format="dita"/>
  <topicref href="chapter-2-3.dita" format="dita"/>
  ...
</map>

とします.こうすればchapterレベルではマップ参照は発生しないので、@outputclassは残ってくれます.でもchapter全体をサブマップに定義したいという要望の場合、手間と感じるかもしれません.

② 自力でbookmapを読み込みchapter/@outputclassを取得する.

DITA-OTに任せるばかりでなく、自分でbookmapを読み込み、このファイルからマージ後中間ファイルのchapterに対応するchapter@outputclassを取得すれば可能です.でも自分で読むためには、スタイルシートも書かねばなりませんし、カタログファイルの設定も必要でちょっとテクニックが要ります.

③ DITA-OTを拡張する.

Eliot Kimberさんから教えてもらったのですが、DITA-OTにはこのようなマップ参照のスタイルシートをカスタマイズする機能があります.

Override styles with XSLT

dita.xsl.mappullという拡張機能(拡張ポイント)があり、これをプラグインで移用する旨宣言すれば、[DITA-OT]/xsl/preprocess/mappullImpl.xslを自分でカスタマイズできるのでしょう.しかしこれをやるにはDITA-OTの内部処理の深い知識が必要です.例えばマップ参照といっても様々なパターンがあり得ます.たまたまchapterから参照している場合は、サブマップの最初のtopicrefに@outputclassを反映させたいのですが、スタイルシートを見る限りそう簡単ではなさそうです.

という訳で簡単&お手軽の順では①>②>③となりそうです.なかなかマップ参照といっても簡単ではありませんね.