DITA 1.3とRELAX NG(3)

DITAとRELAX NGについてもう少し勉強しましたので、書いてみたいと思います.

DITAのスキーマRELAX NGを導入することは突然降って沸いたのではなく、すでに2010年頃からoXygenのSyncrosoftのメンバーとEliot Kmberさんにらによって進められてきたものです.このプロジェクトは以下でホストされています.

dita-ng
DITA implementation in Relax NG

ここには2013年4月付けのZIPがあり、これを解凍するとDITA Open Toolkitのスキーマプラグインフォルダorg.dita-ng.doctypesが現れます.これをDITA-OT/pluginsにコピーしてant -f integrator.xmlとやればスキーマが使えるようになります.

実はXML EditorのoXygenはこれを使用してすでに相当以前からエディタのIDE上で

1、RELAX NGで検証するDITAのmapやtopicを作る.
2、oXygen組み込みのDITA-OTでRELAX NGで検証してpublishingする.

が出来るようになっていました.

[oXygenでのRELAX NGで検証するtopic]

イメージ 1


これらの開発のいきさつは、XML Prague 2011の以下のURLからoXygenのSyncro Softの創設者の一人であるGeorge Cristian Binaさんによるプレゼンテーションで知ることができます.

DITA NG A RelaxiNG implementation of DITA

ここには、何故いままでRELAX NGでDITAを検証し、動かすことができなかったのか?そしてそれをどのように解決したのかが簡単に説明されていて興味深く読むことがでいます.

まずそもそものRELAX NGというスキーマですが、DTDXML Schemaとはある意味相当毛色の異なる考え方をしています.そしてそれがDITAで使えない原因になっていたようです.

RELAX NGの特徴ですがO'Reillyの「RELAX NG」を読むと次のように説明されています.


"スキーマ言語は(検証するXMLの)制約条件を定義するのに異なった方法を取っています.
スキーマトロンは制約条件をルールとして表現しています.
DTDXML Schemaは個々の要素や属性の記述で表現しています.
RELAX NGは許される要素や属性テキストノードの「パターン」として表現しています."

普段DTDXML Schemaを使っている人間からするとやはりRELAX NGは別格です.ともかくパターンマッチングの世界で検証するのですから.

ところがこのパターンマッチングと言う考え方は、スキーマで属性の初期値を決めるというDTDXML Schemaではあたりまえのことと相容れません.

しかしDITAでは御存知のようにすべての要素にはclass属性があって、パーサーを通すとここに既定値がはいる大前提になっています.class属性はDITAの特殊化なくてはならない属性です.ここが第一の問題でした.

これはRELAX NGの次の仕様で注釈をつけることで解決されました.

RELAX NG DTD Compatibility
Committee Specification 3 December 2001

例えばtopic/titleはDTDでは、

<!ATTLIST title     %global-atts;  class CDATA "- topic/title "      >

のようにして既定値を定めています.RELAX NGではこれは注釈(Annotation)で記述されます.以下の"a:"のネームスペースプリフィックスが注釈のネームスペースの"http://relaxng.org/ns/compatibility/annotations/1.0"を表しています.

  ...
<define name="title.attlist" combine="interleave">
  <ref name="global-atts"/>
  <optional>
    <attribute name="class" a:defaultValue="- topic/title "/>
  </optional>
</define>

しかしここまでで既定値の記述は可能になっていますが、処理系が注釈を見てくれないと困ります.これはJames Clarkが開発したRELAX NGの検証ツールのJingを改造することによって実現されました.George Cristian Binaさんにのプレゼンテーションでは次のように記述されています.

Extracting annotations from Jing
● Change Jing to store attribute default values annotations
● Implement a component that parses a schema and creates a map between 
   attributes and their default values

(以下続く)