以前DITAをサポートしているけっこう有名なCMSのエンジニアの方にうかがったことがありますが、そのCMSはDTDしかサポートしていないとのことでした.文書のバリデーションはDITA Open Toolkitでビルドするときに最初のステップで行われます.ビルドの直前までバリデーションなしだといざというときにエラーがでてしまうと大変なので、CMSやオーサリングツール(例えばXMetal)はバリデーションをサポートしているはずなのです.まだみんなDTDのようなのですが、もはやDTDは時代遅れの感を否めません.
DITA Open ToolkitはJavaソリューションでLinuxでもMacでもJavaさえあれば動かせますが、オーサリングのプラットフォームは基本的にWindowsだと思います.このXMLスキーマ、オーサリングの際に利用できないかなあ?と考えました.
昔MicrosoftがWord2003を出したときに、WordでXMLも作れると言って大々的に宣伝したことがあります.実際Word2003は、単純なXMLだったらそれをピンクのタグつきで表示し編集できました.もっとちゃんとやるためにはXMLスキーマを作ってXML文書に関連付けてやれば、カーソルのある箇所で挿入できる要素を示してくれたり、属性も編集できたはずだったと思います.(もはや昔のことなので詳細は忘れてしまいました)でもこの機能はカナダの会社が特許権を侵害していると訴えたため、Word2007からは残念ながらなくなってしまいました.
Word2003がどのようにこのXMLオーサリング機能を実装しているかというと、想像ですがMSXML5のSOM(Schema Object Model)を使っていたんじゃないかと思います.XML文書に関係付けられたXMLスキーマを読み込んで、挿入可能な要素を示したり、属性をスキーマに定義されたものに従って入力可能にしていたのです.
このサンプルプログラムを使って、DITA Open Toolkitの[DITA-OT]/schema/bookmap/xsdbookmap.xsdを処理します.すると以下のようなエラーの山になります.
WARNING: 'schemaLocation' 属性を解決できません。
ERROR: 'SchemaLocation' は、<redefine> が <annotation> 以外の子を含む場合は、正常に解決しなければなりません。
ERROR: 'SchemaLocation' は、<redefine> が <annotation> 以外の子を含む場合は、正常に解決しなければなりません。
ご存知かもしれませんが、DITA-OTのXMLスキーマはDTD同様、その1ファイルで完結していません.他の多くのモジュールをインクルードしています.そしてそのインクルードしているスキーマはパスではなくURIで示されているのですが、これはカタログファイル([DITA-OT]/catalog_dita.xml)を使わないと解決できないのです.
<!-- インクルードの例 -->
<xs:include schemaLocation="urn:oasis:names:tc:dita:xsd:mapGroupMod.xsd:1.2" />
<xs:include schemaLocation="urn:oasis:names:tc:dita:xsd:mapGroupMod.xsd:1.2" />
<!-- catalog_dita.xmlの対応する行 -->
<system systemId="urn:oasis:names:tc:dita:xsd:mapGroupMod.xsd:1.2" uri="mapGroupMod.xsd" xml:base="schema/base/xsd/"></system>
<system systemId="urn:oasis:names:tc:dita:xsd:mapGroupMod.xsd:1.2" uri="mapGroupMod.xsd" xml:base="schema/base/xsd/"></system>
Javaだったらこのカタログファイルの処理は、かのNorman Walshさんが作った有名な[DITA-OT]/lib/resolver.jarがやってくれます.でも.NETプラットフォームの標準のSystem.Xml.XmlUrlResolverはカタログファイルをサポートしていません.エラーが出て当然です.で、.NETでカタログファイルをサポートしているプロジェクトがないか探してみました.すると次のサイトのLONDATAがApacheライセンスで.NETのクラスを公開していました.
さっそくダウンロードしてみましたが、やってみてわかった問題はこのNet.xmlcatalogクラスが、log4netを使っていることです.log4netは、log4jの.NET版のようでApacheのサイトにあるのですが、.netのバージョン1や2のアセンブリを参照している古いコードがあって、VS2010の全然ビルドを通りません.仕方がないので、Net.xmlcatalogクラスからlog4netへの参照をすべてコメントアウトして無理やりエラーを取りました.(本当はターゲットを.netのバージョン2とかにすればよいのかもしれないけれど、私は.netはまるっきりの初心者なので...)
その結果が以下のコードです.
ただ
Imports Net.xmlcatalog
と
schemaSet.XmlResolver = New XmlCatalogResolver("D:\DITA-OT1.5.2-FB\catalog-dita.xml")
と
schemaSet.XmlResolver = New XmlCatalogResolver("D:\DITA-OT1.5.2-FB\catalog-dita.xml")
の2行を加えたのみです.
これでめでたくbookmap.xsdのコンパイルが一発で通り、SOMのオブジェクトを見られるようになりました.あとから考えたら当然だったのですが、CMSはどうみても.netのプラットフォームで動いているように見えます.でもこのSOMは当初からXMLスキーマを対象として作られていて、DTDはサポートしていません.
「XML スキーマは、XML ドキュメント準拠の構造を作成し検証する、強力な複合ツールです。リレーショナル データベースのデータ モデリングと同様に、スキーマでは XML ドキュメントの構造を定義する方法を提供しています。これは、ドキュメントで使用する要素と、これらの要素に固有のスキーマを有効にするために準拠する構造や型を指定することによって実現します。スキーマ オブジェクト モデル (SOM) は、クラスのセットを System.Xml.Schema 名前空間に提供し、それによってファイルからスキーマを読み取ったり、プログラムを使用してスキーマをメモリ内に作成したりできるようになります。その後、スキーマの走査、編集、コンパイル、検証、またはファイルへの書き込みが可能になります。(SOMの説明より引用)」
どおりで、CMS経由で渡されるDITAのインスタンスには、直接DTDのパスが書いてある理由がわかりました.DTDがSOMで使えればこんな苦労などしなくて済むのですが、CMSのカスタマーエンジニアの方は必死にDTTAのDTDを書き換えて自分のCMSで動くようにしているのです.
<!--CMSに格納されている文書の文書型宣言の例 -->
<!DOCTYPE bookmap PUBLIC "-//OASIS//DTD DITA BookMap//EN" "file:///C:/XxxxXxxxxx/Web/Author/ASP/DocTypes/dita-oasis/1.2/dtd/bookmap.dtd" []>
<!DOCTYPE bookmap PUBLIC "-//OASIS//DTD DITA BookMap//EN" "file:///C:/XxxxXxxxxx/Web/Author/ASP/DocTypes/dita-oasis/1.2/dtd/bookmap.dtd" []>