DTDと名前空間の組み合わせで生じる不都合とは?
DTDは名前空間に対応していない、もしくは相性がよくないといわれていますが、具体的にはどんな不都合が発生するのですか?

回答/富士ソフトABC株式会社 技術センター
2001/12/7

 まず、XML名前空間の特徴を確認しておきましょう。

 XML名前空間は、既存のXMLのボキャブラリの再利用を主な目的に考え出されたものです。要素や属性などの意味を持った定義である既存のボキャブラリとほとんど同等な新たなボキャブラリを再開発するのではなく、再利用することによってコストや開発期間の短縮を可能にします。

 例えば、要素や属性などのタグセットがXHTMLとほとんど同じで、その中に独自の情報を埋め込んで使用したい場合など、名前空間によってそれぞれのタグセットを区別するような用途が想定されます。

 では、DTDを使用する場合に生じる名前空間との不整合に関して、簡単な例を示して説明しましょう。以下のようなDTDとXML文書を用意します。

<?xml version="1.0" encoding="Shift_JIS"?>
<!ELEMENT 書籍情報 (書籍*)>
<!ELEMENT 書籍 (書籍名,作者)>
<!ATTLIST 書籍 管理番号 CDATA #REQUIRED>
<!ELEMENT 書籍名 (#PCDATA)>
<!ELEMENT 作者 (#PCDATA)>
リスト1 一般的なDTDの例

<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE 書籍情報 SYSTEM "rei1.dtd">
<書籍情報>
    <書籍 管理番号="1">
        <書籍名>XML名前空間</書籍名>
        <作者>何野 誰平</作者>
    </書籍>
</書籍情報>
リスト2 上記のDTDに従って作成されたXML文書

 このXML文書は、妥当なXML文書です。そして、このXML文書に名前空間を適用すると、次のようになります。

<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE myname:書籍情報 SYSTEM "rei1.dtd">
<myname:書籍情報 xmlns:myname="http://test.com/test2">
  <myname:書籍 管理番号="1">
    <myname:書籍名>XML名前空間</myname:書籍名>
    <myname:作者>何野 誰平</myname:作者>
  </myname:書籍>
</myname:書籍情報>
リスト3 名前空間をリスト1に対して適用してみる

 注意しなければいけないのは、リスト3のXML文書は整形式のXML文書ではありますが、妥当なXML文書ではなくなってしまったことです(要素名がDTDで定義したものと変わってしまったため)。

 DTDでは名前空間を表現する場合にも、あらかじめ要素名などに接頭辞を付加した形で記述する必要があります。名前空間接頭辞とは、名前空間名(Namespace Name)を省略して表記するためのものです。

 そこで、名前空間を適用したDTDとXML文書を作成するとすれば、以下のようになります(リスト4、リスト5)。

<?xml version="1.0" encoding="Shift_JIS"?>
<!ELEMENT myname:書籍情報 (myname:書籍*)>
<!ATTLIST myname:書籍情報
xmlns:myname CDATA #FIXED "http://test.com/test3">
<!ELEMENT myname:書籍 (myname:書籍名,myname:作者)>
<!ATTLIST myname:書籍 myname:管理番号 CDATA #REQUIRED>
<!ELEMENT myname:書籍名 (#PCDATA)>
<!ELEMENT myname:作者 (#PCDATA)>
リスト 4 名前空間接頭辞を付けて定義したDTD

<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE myname:書籍情報 SYSTEM "rei3.dtd">
<myname:書籍情報>
  <myname:書籍 myname:管理番号="1">
    <myname:書籍名>XML名前空間</myname:書籍名>
    <myname:作者>何野 誰平</myname:作者>
  </myname:書籍>
</myname:書籍情報>
リスト5 DTDで定義した名前空間接頭辞のタグを使ったXML文書

 このように記述すればDTDを用いて名前空間を使用できますが、いくつか問題が発生します。まず、接頭辞に「myname」を使用していますが、この接頭辞をほかのものに変更する場合、DTD側も変更する必要があります。これでは、名前空間の勧告と矛盾してしまいます。勧告では接頭辞の宣言位置にも自由度がありますが、DTDを使用する場合にはこの自由度がなくなって固定されることになり、勧告と矛盾するのです。

 最も問題だと思われるのは、下記のようにXHTMLの中に、独自のタグを埋め込んで利用したい場合でしょう。XHTMLに、独自で定義したタグを組み込む場合には、Modularization of XHTML (W3C勧告) を利用することになります。

 このとき、独自タグとXHTMLのタグは、名前空間によって区別されるのですが、こうした名前空間が混在した文書をDTDで定義することはとても困難です。それは、XHTMLが持つモジュール機能と、それを表現するために「DTDドライバ」という新しい機能を習得して記述しなければならないからです。

 しかも、上記勧告の「D.2.4. Namespace Idiosyncrasies」にも触れられているように、この方法でも、DTDではXML Namespace勧告のすべてをカバーすることはできません。それは、下記の制限によるものです。

  • 名前空間の接頭辞を変更できない(固定される)
  • 名前空間の宣言位置が固定される

 しかもInternet Explorer(もしくはMSXML)では、そもそもDTDドライバやDTDフラグメントといった新しい機能をサポートしていないので、実際の利用面ではDTDによる名前空間の定義は大きく制限されます。そうした問題が含まれる例を、リスト6、7に示しました。

<?xml version="1.0" encoding="Shift_JIS"?>
<?xml-stylesheet type="text/xsl" href="rei4.xsl"?>

<!-- IEで確認する場合は、下記とコメントを入れ替え -->
<!-- rei4.dtd (DTDドライバ) は、Modularization of XHTML
〜〜 の取り込みや、書籍情報のためのモジュール(rei4.mod)を
〜〜 定義している。 -->
<!DOCTYPE html SYSTEM "rei4.dtd" [
<!ENTITY % MyName.prefixed "INCLUDE">
]>

<html>

<!-- IE用 〜 IE、MSXMLのバージョンによるが、上記のDTD が処理されない
〜〜 のでエラーになる。そのための代替処置
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:myname="http://www.rei4.com/rei4"
xml:lang="jp">
〜〜 IE用 -->

  <head>
    <title>test4</title>
  </head>
  <body>
    <h1>Test4</h1>
    <p>名前空間の使用例</p>
    <!-- XHTML 内に独自の構造を追加している -->
    <!-- 書籍情報以外は、XHTMLの定義をそのまま使用できる -->
    <myname:書籍情報>
      <myname:書籍 myname:管理番号="1">
        <myname:書籍名>XML名前空間</myname:書籍名>
        <myname:作者>何野 誰平</myname:作者>
      </myname:書籍>
       <myname:書籍 myname:管理番号="2">
        <myname:書籍名>DTD</myname:書籍名>
        <myname:作者>匿名 希望</myname:作者>
      </myname:書籍>
    </myname:書籍情報>
  </body>
</html>
リスト6 XHTMLに独自タグを追加するXML文書

<?xml version="1.0" encoding="Shift_JIS"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
  <xsl:template match="/">
    <html>
      <head><title><xsl:value-of select="html/head/title" /></title></head>
      <body><xsl:apply-templates select="html/body" /></body>
    </html>
  </xsl:template>
  <xsl:template match="html/body">
    <xsl:apply-templates select="h1|hr|p" />
    <xsl:apply-templates select="myname:書籍情報" />
  </xsl:template>
  <xsl:template match="h1|hr|p">
    <xsl:copy><xsl:value-of /></xsl:copy>
  </xsl:template>
  <!-- データを取り出します -->
  <xsl:template match="myname:書籍情報">
    <xsl:for-each select="myname:書籍">
      <hr />
      書籍名: <xsl:value-of select="myname:書籍名" /><br />
      作 者: <xsl:value-of select="myname:作者" /><br />
    </xsl:for-each>
    <hr />
  </xsl:template>
</xsl:stylesheet>
リスト7 XHTMLに独自タグを追加するXSLTスタイルシート(実際に試すには、rei4.xmlrei4.xslrei4.modrei4.dtdを用いる)。

 これらに関して詳しい内容は「JIS TR X 0023:1999 XML名前空間」の「XML名前空間 解説解説」で指摘されていますので確認してみてください。

 このほかにもDTDに関する問題として、以下のような事項が一般的に知られています。

  • DTDがXMLと別の書式を用いていること
  • データ型が用意されていないこと
  • 要素の出現回数などの規定に制限があること

 これらの問題を解決するために、DTDに代わって名前空間に対応し、豊富な機能を持つスキーマ言語として、XML SchemaやRelax NGなどが提唱されています。

■関連記事
XMLを学ぼう第4回 スキーマ言語「DTD」の機能と役割
XMLを学ぼう第5回 DTDを読んでみよう
XMLを学ぼう第7回 ボキャブラリを拡大する「名前空間」

 

「Ask XML Expert」


XML & SOA フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

HTML5+UX 記事ランキング

本日月間