DITA-OT標準のリテラル文字列を変更/追加する

ずっとXL-FO⇒PDF一本でしたが最近はHTMLもやっています.HTMLというとDITA-OTについてくるプラグインはまだまだそっけないですが、oXygenについてくるWeb Helpはそこそこの見栄えもあって完成度も高く、使用しておられるお客様も多いようです.

さて、Web Helpのスタイルシートを解析して行くと、これは完全にoXygenが作ったものではなく、DITA-OTのXHTMLプラグインスタイルシートをインポートしていることがわかります.例えば

C:\Program Files\Oxygen XML Editor 18.1\frameworks\dita\DITA-OT2.x\plugins\com.oxygenxml.webhelp\xsl\dita\dita2webhelp.xsl

  <xsl:import href="plugin:org.dita.xhtml:xsl/dita2xhtml.xsl"/>

普通のパス記述でなくてビックリするかもしれませんが、これはカタログファイルを使っているからです.

C:\Program Files\Oxygen XML Editor 18.1\frameworks\dita\DITA-OT2.x\catalog-dita.xml

<rewriteURI uriStartString="plugin:org.dita.xhtml:" rewritePrefix="plugins/org.dita.xhtml/"/>

さて標準のDITA-OTのXHTMLプラグインを使っていると、日本語のリテラル文字列もoXygenのWeb Help側にある訳ではなく、DITA-OTで標準で持っているものが使用されます.これをたまたま修正したい場合があります.例えば

<note type="note">この機能はNX-9000シリーズのみで有効です。</note>

などといったオーサリングがあった場合、DITA-OTは見出しの文字列として「注」を割り当てます.これはけっして間違いではありませんが、お客様によってはnoteを「参考」というコンテキストで使用されているケースがあります.このようなお客様向けにカスタマイズしたいのですが、私は(恥ずかしながら)その方法を知りませんでした.そこでDITA-OT Usersグループで聞いてみたところ次のURLを教えてもらえました.

Modifying or adding generated text

ここのガイドラインに従うと、新しい文字列を定義したプラグインを作れば良いようです.以下はそのサンプルです.

1. [DITA-OT]/com.acme.dita.stringというプラグインフォルダを作ります.
2. [DITA-OT]/com.acme.dita.string/plugin.xmlは次のようにします.

<plugin id="com.acme.dita.string">
  <feature extension="dita.xsl.strings" file="xsl/strings-acme.xml"/>
</plugin>

3. 書き換える文字列は言語別に定義します.

[DITA-OT]/com.acme.dita.string/xsl/strings-acme.xml

<?xml version="1.0" encoding="UTF-8"?>
<langlist>  
  <lang xml:lang="ja" filename="strings-ja-jp.xml"/>
  <lang xml:lang="ja-jp" filename="strings-ja-jp.xml"/>
</langlist>

[DITA-OT]/com.acme.dita.string/xsl/strings-ja-JP.xml

<?xml version="1.0" encoding="UTF-8"?>
<strings xml:lang="ja-JP">
  <str name="Note">参考</str>
  <str name="Notes">参考</str>
</strings>

أNoteとNotesの使い分けがいまいちわからないのですが(オイオイ)このプラグインを作って、[IDTA-OT]でコマンドプロンプトを立ち上げ、bin\dita -installでプラグインを組み込むとnote要素の見出し文字列はめでたく「注」から「参考」に替わってくれました.

実は組み込みによって以下のファイルが変わっています.

D:\DITA-OT\dita-ot-2.4.2\xsl\common\strings.xml

  <lang xml:lang="ja" filename="../../plugins/com.acme.dita.string/xsl/strings-ja-jp.xml"/>
  <lang xml:lang="ja-jp" filename="../../plugins/com.acme.dita.string/xsl/strings-ja-jp.xml"/>


このようなプラグインを使っての文字列の書き換えは確かに便利なのですが、特定のプラグインのみ有効にするということが出来ないので注意が必要です.つまりいったんこのプラグインを組み込んでしまうと、DITA-OTの標準のリテラル文字列を使っているプラグインはすべて「注」→「参考」になってしまうのです.更に文字列の書き換えが競合した場合の動作は「he results will be non-deterministic」(予測がつかない!)になります.

まあDITA-OTはシステムに一個だけしか置けないという決まりはないので用途によりいくらでもDITA-OTをフォルダを分けて使うことはできるのですが、それでも1つのプラグインのカスタマイズが全体に影響を与えてしまうというのはちょっといただけない感じもします.

あとソフトウェアのユーザーズマニュアルなんかを作っているとき、メニュー操作で「[ファイル] > [名前をつけて保存]を選択します.」などと書くことが頻繁にありますが、このような場合たいてい次のようにオーサリングします.

<menucascade><uicontrol>ファイル</uicontrol><uicontrol>名前をつけて保存</uicontrol></menucascade>

ところがここでも発生するのですが、お客様によっては「[ファイル] > [名前をつけて保存]を選択します.」でなくて「[ファイル]-[名前をつけて保存]を選択します.」と表記したい場合もあるのです.ところがあにはからんやこれは文字列の書き換えでは対応できません.何故かというとmenucascadeの区切り文字" > "はスタイルシート中にハードコードされているからです.例えばXHTMLでしたら

C:\Program Files\Oxygen XML Editor 18.1\frameworks\dita\DITA-OT2.x\plugins\org.dita.xhtml\xsl\xslhtml\ui-d.xsl

<xsl:template match="*[contains(@class,' ui-d/uicontrol ')]" name="topic.ui-d.uicontrol">
<!-- insert an arrow with leading/trailing spaces before all but the first uicontrol in a menucascade -->
<xsl:if test="ancestor::*[contains(@class,' ui-d/menucascade ')]">
 <xsl:variable name="uicontrolcount"><xsl:number count="*[contains(@class,' ui-d/uicontrol ')]"/></xsl:variable>
  <xsl:if test="$uicontrolcount&gt;'1'">
    <xsl:text> > </xsl:text>
  </xsl:if>
</xsl:if>
 <span class="uicontrol">
  <xsl:call-template name="commonattributes"/>
  <xsl:call-template name="setidaname"/>
  <xsl:apply-templates/>
 </span>
</xsl:template>

oXygenのWeb Helpの場合、テンプレートのオーバーライドをする拡張機能がありますので、それを使用して次のようなプラグインのテンプレートを作ります.

C:\Program Files\Oxygen XML Editor 18.1\frameworks\dita\DITA-OT2.x\plugins\com.acme.xhtml\plugin.xml

<plugin id="com.acme.dita.xhtml-extensions">
    <feature extension="com.oxygenxml.webhelp.xsl.dita2webhelp" file="xsl/ui-d.xsl"/>
</plugin>

C:\Program Files\Oxygen XML Editor 18.1\frameworks\dita\DITA-OT2.x\plugins\com.acme.xhtml\xsl\ui-d.xsl

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="2.0"
     exclude-result-prefixes="dita-ot">
<xsl:template match="*[contains(@class,' ui-d/uicontrol ')]" name="topic.ui-d.uicontrol">
  <xsl:if test="ancestor::*[contains(@class,' ui-d/menucascade ')]">
    <xsl:variable name="uicontrolcount"><xsl:number count="*[contains(@class,' ui-d/uicontrol ')]"/></xsl:variable>
      <xsl:if test="$uicontrolcount&gt;'1'">
        <xsl:call-template name="getVariable">
            <xsl:with-param name="id" select="'Menucascade'"/>
        </xsl:call-template>
     </xsl:if>
   </xsl:if>
   <span class="uicontrol">
     <xsl:call-template name="commonattributes"/>
     <xsl:call-template name="setidaname"/>
     <xsl:apply-templates/>
   </span>
</xsl:template>

</xsl:stylesheet>

これで先ほどの文字列の変更に戻って、次のようにmenucascadeの区切り文字列を新たに定義してやります.

[DITA-OT]/com.acme.dita.string/xsl/strings-acme.xml

<?xml version="1.0" encoding="UTF-8"?>
<langlist>  
  <lang xml:lang="ja" filename="strings-ja-jp.xml"/>
  <lang xml:lang="ja-jp" filename="strings-ja-jp.xml"/>
  <lang xml:lang="en" filename="strings-en-us.xml"/>
  <lang xml:lang="en-us" filename="strings-en-us.xml"/>
</langlist>

[DITA-OT]/com.acme.dita.string/xsl/strings-ja-JP.xml

<?xml version="1.0" encoding="UTF-8"?>
<strings xml:lang="ja-JP">
  <str name="Note">参考</str>
  <str name="Notes">参考</str>
  <str name="Menucascade"> - </str>
</strings>

[DITA-OT]/com.acme.dita.string/xsl/strings-en-US.xml(英語は"-"でなく"-"を使う)
<?xml version="1.0" encoding="UTF-8"?>
<strings xml:lang="en-US">
  <str name="Menucascade"> - </str>
</strings>

"getVariable"というテンプレートはそれなりにxml:lnagを識別して、該当の文字列を取ってきてくれるようです.これで「[ファイル]-[名前をつけて保存]を選択します.」が実現できました.(注:英語の方はまだデータがないので未テストです.)

oXygenのWeb Helpはカスタマイズが可能で、まだまだ奥深いところがあります.例えばキーワードによる文字列検索を実現していますが、これをどのように効果的に使うかなど、けっこう調べなければなりません.開発者はoXygenのRadu Pisoiという方ですが、oXygenのフォーラムでの応答もすぐですし今後が楽しみです.