DITAでMathMLを使う.

あるお客様からどうしてもDITAでMathMLを使いたいという話がありました.マニュアルで数式を使わなければならないからです.確かに世界を見渡せばいろいろ苦労して使っていらっしゃる方はいるみたいです.
 
 
DITAの仕様では、<foreign>という要素が、「コンテンツはなんでもいいよ!」ということになっていて事実上MathMLとかSVGのコンテナになっています.でも実際にDTDで運用しようとすると、MathMLやSVGDTDを用意してやらなければならずたぶん大変です.いわゆる「特殊化」をやらなければならないからです.DITAのDTDでは、<foreign>の箇所は、
 
<!ENTITY % foreign.content "ANY">
<!ELEMENT foreign    %foreign.content;>
 
とはなっていますが、ANYは「DTDで宣言されたすべての要素を含むことができる」というもので、宣言もされていないMathMLの要素を書くことはできません.実際DITA-OTのディストリビューションにはMathMLのDTDなどついてこないのです.自力でDTDをつけて修正しなければなりません.やっぱりDTDは大変です.もっと簡便な方法がないかな~といろいろ考えました.XML Schemaの方を調べてみるとこうなっています.
 
<xs:element name="foreign">
    <xs:annotation>
        <xs:documentation>...省略...</xs:documentation>
    </xs:annotation>
    <xs:complexType>
        <xs:complexContent>
            <xs:extension base="foreign.class">
                <xs:attribute ref="class" default="- topic/foreign "/>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
</xs:element>
<xs:complexType name="foreign.class">
    <xs:sequence>
        <xs:group ref="foreign.content"/>
    </xs:sequence>
    <xs:attributeGroup ref="foreign.attributes"/>
</xs:complexType>
<xs:group name="foreign.content">
    <xs:sequence>
        <xs:sequence>
            <xs:choice minOccurs="0" maxOccurs="unbounded">
                <xs:any processContents="skip"/>
            </xs:choice>
        </xs:sequence>
    </xs:sequence>
</xs:group>
 
ここの<xs:any processContents="skip"/>がミソですね.パーサーは<foreign>の中を検証しないのです.つまり何を書いてもOKのはずです.(まあ整形式くらいは必要でしょうが...)
 
そこで、次のようなtopicを作ってみました.今までは文書型宣言をつけているのが常識でしたが、今度はXMLスキーマのnoNamespaceSchemaLocation属性の指定です.mapも同じように変更しました.
 
<?xml version="1.0"?>
<topic xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="urn:oasis:names:tc:dita:xsd:topic.xsd"
       id="topic_9940DF80A456CF4C97AB5560">
 <title>Foreign testing</title>
 <shortdesc>The foeign (&lt;foreign&gt;) element allows the introduction of non-DITA content, for example, MathML, SVG, or Rich Text Format (RTF). </shortdesc>
 <body>
        <section>
            <title>Foreign sample for MathML</title>
            <foreign>
                <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML">
                <mrow><mo>[</mo> <mrow>
                   ...MathMLは長いので省略.
                  </mrow> <mo>]</mo></mrow>
                </math>
            </foreign>
        </section>
    </body>
</topic>
 
あとはスタイルシートです.XSL-FOばかりですみませんが、単純に<foreign>の中をチェックして、MathMLだったらfo:instream-foreign-objectを生成するようにしてみました.
 
<xsl:template match="*[contains(@class, ' topic/foreign ')]">
    <xsl:variable name="childElem" select="child::*[1]" as="element()*"/>
    <xsl:if test="exists($childElem) and (namespace-uri($childElem)='http://www.w3.org/1998/Math/MathML';)">
        <fo:instream-foreign-object content-type="content-type:application/mathml+xml">
            <xsl:copy-of select="$childElem"/>
        </fo:instream-foreign-object>
    </xsl:if>
</xsl:template>
 
これでDITA-OTを通してPDFにした結果が以下のイメージです.おお!何とかMathMLが描画できています.
XML SchemaってDTDより楽ですね.お客様にこの方法を提案してみようと思います.
 
イメージ 1
 
(注:XML SchemaがいかほどDITAで使われているかを知りません.著名なCMSDTDサポートのみと聞きます.MathMLも手でエディタで入れればなんの問題もないですが、オーサリングツールと無関係ではいられないでしょう.この方法は、オーサリングに自由がきいて、CMSなど使わずDITAを小規模で作るのに向いているのかもしれません.)