スキーマ言語「DTD」の機能と役割XMLを学ぼう(4)

XMLを解説した記事や書籍では、「DTD」の解説をしているものが多いが、このDTDにつまずく入門者も多い。なぜXMLにはDTDが存在するのか、DTDとはなにか、そしてDTDの意味について、今回は解説していこう。

» 2000年08月26日 00時00分 公開
[川俣晶株式会社ピーデー]

DTDという言葉をよく聞くが……

 XML関係の資料を見ていると、しばしば、DTDという言葉を見かける。DTDは「Document Type Definition」の略で、日本語では「文書型定義」と呼ぶ。

 XMLは簡単な技術であり、簡単なXML文書を書く方法を修得するのは容易である。ところが、XMLに関する本格的な勉強を、と思うと、DTDで挫折してしまうことが多い。XML入門者にとって、DTDは大きな障壁の1つなのは間違いない。

■DTDはどうしても必要?

 だが、どうしてもDTDを修得しなければXMLは使えないのだろうか?

 結論を最初に述べる。

 DTDは、いわゆるXMLのスキーマ言語と呼ばれているカテゴリーの言語の1つである。同じカテゴリーには、XML SchemaやRELAXという言語が存在する。基本的には、DTDではなくXML SchemaやRELAXを使用するという選択もあり得るので、どうしてもDTDでなければならない、ということはない。しかし、これらがDTDよりも簡単に理解できるかというと、そうではない。スキーマ言語は抽象性の高いものなので、もともと理解しにくいものなのだ。DTDが難しいのは、DTD自身の問題ではなく、スキーマ言語全般が持っている宿命のようなものだと言える。むしろ、スキーマ言語の中では、DTDは簡単なほうだと言える。

 最初の質問の本当の意味はこう言い直すべきなのだ。

 どうしてもスキーマ言語を修得しなければXMLは使えないのだろうか?

 XMLの仕様書に沿って答えるならば、ノーである。DTDを含まないXML文書も、XMLの仕様に適合する文書であると見なされる。

 つまり、DTDという障壁を乗り越えるのではなく、迂回して進むことも可能である。

 しかし、迂回すれば問題はすべて解決されると言うわけではない。

 DTDやスキーマ言語は、ただ単に、XMLの学習を難しくするために存在するわけではないのだ。当然、それを便利だと思い、歓迎する人達がいるからこそ、そこに存在するものなのである。

 難しいのに便利、というのは分かりにくいかもしれないが、1つの真実である。

 つまり、スキーマ言語の大きな壁を乗り越えれば、その苦労に値するだけの大きな利便性を手に入れられる、ということなのである。

 それでは、いったいどんな利便性が手に入るのだろうか?

スキーマ言語の機能と役割

 昔誰もが受けた算数〜数学の時間を思い出してほしい。まだ現役の人は、いま学校で受けている授業のことを考えてほしい。

 例えば、足し算というものがある。最初には、1足す1は2、といった計算方法を学ぶ。それによって、147円の商品と280円の商品を買うといくらになるでしょう、といった問題に答えられるようになる。

 ところが、このように具体性が豊富で直感的にイメージしやすい世界は長続きしない。すぐに、具体的な数字が消えて、xだのyだのと言った文字に置き換えられる。x足すyはいくつでしょう? と言われて、すぐに具体的なイメージが浮かぶ人は多くはない。

 では、計算を具体的な数字で表現しないことは、難しいだけで無意味なのだろうか?

■抽象化することにも意味がある

 そうではない。例えば、土地を買うときに、同じぐらいの広さの長方形の土地と台形の土地があったとする。本当に広いほうの土地を買いたいと思ったとき、長方形の面積は縦かける横、台形の面積は(上辺足す下辺)割る2掛ける高さ、といった公式を知っていれば、すぐに計算して面積を比較できる。このような便利な公式は、当然、具体的な数値が入っていないからこそ意味があるのだ。どんな数値がこようとも、それを当てはめるだけで、すぐ計算できるから意味がある。

 では、自分で公式を作るというケースを考えてみよう。当然、公式は特定の数値を最初から入れておくわけにはいかないので、数値のかわり、xやyといった文字を入れておく。もちろん、具体的な数値(林檎と蜜柑の数や、土地の面積)などをイメージできないから、公式を作るというのはとても分かりにくい作業だ。だが、この作業を乗り越えると、あとは、数値を当てはめて計算するだけで結果が出る便利な手段が得られることになる。

 スキーマ言語は、ここでいう公式のようなものである。

■スキーマ言語は公式のようなもの

 例えば、在庫を管理する在庫言語をXMLで作るとしよう。以下のようなXML文書で在庫を表現するというのは一目瞭然、非常に具体的で、誰でも見れば分かるだろう。

<在庫>
  <品名>林檎</品名>
  <個数>5</個数>
</在庫>

 ここでは「林檎」や「5」という内容は非常に具体的である。しかし、いつも「林檎」だとはかぎらない。「蜜柑」を在庫する場合もあるかもしれない。そして、在庫する個数は常に5個とはかぎらない。では、数式のように、xやyを使って書くと、どうなるだろう?

<在庫>
  <品名>x</品名>
  <個数>y</個数>
</在庫>

 このような文書を作っておき、「実際に使うときはxは品名に置き換えて下さい。yは個数に置き換えて下さい」と書き添えておけば、誰でもすぐに、さまざまな在庫言語のXML文書のバリエーションを書くことが可能になる。このような規範となるXML文書を、ちょっと抽象的に書いておくと便利である。

 ところが、あらゆるXML文書をこのような方法で表現するのは無理がある。なぜかというと、XMLでは、以下のような書き方が可能だからだ。

 まず、要素の任意回数の繰り返しができる。1個書いてもよいし100個書いてもよい、というパターンがよく使われる。例えば、在庫を管理するなら、在庫する品物が1種類とは考えられない。何種類もあるが数は状況に応じて変化するだろう。繰り返す個数が決まっていなければ、上記のようなXML文書は書けない。また、書いても書かなくてもよい、という要素を使うこともよくある。さらに、親要素に書いても子要素に書いてもよい、という要素もある。

 例えば、HTML(XHTML)の書き方のルールを考えてみれば、上記のような規範的な文書を作れないことが分かるだろう。段落や見出しが何個出現するか分からないというだけで、上記のような単純な書き方では対応できないのである。

 これらの複雑なXML文書に対応するには、もっと抽象度を高めなければならない。これがいわゆるXMLのスキーマ言語である。そして、DTDもその1つである。

DTDの表記に置き換えてみる

 上記の規範を、DTDの文法に沿って書き換えると、以下のようになる。

<!ELEMENT 在庫 (品名,個数)>
<!ELEMENT 品名 (#PCDATA)>
<!ELEMENT 個数 (#PCDATA)>

 突然、ここからできあがるXML文書の具体的なイメージがまったく連想できなくなるほど、非常に抽象的な表記に大きく変わったことが分かると思う。だが、このような抽象的な表記にすることで、さまざまなものを表現できるようになった。

 それを説明する前に、上記のサンプルが何を主張しているのかを説明しよう。

■DTDの中身はどうなっている?

 まず、“<!ELEMENT”で始まる構文は、DTDの中で、要素に関する宣言を行う機能を示す。そして、それに続いて書かれた名前が、対象となる要素名を示す。

 1行目は在庫要素、2行目は品名要素、3行目は個数要素についての宣言である。要素名のあとに続いて記述された内容が、具体的にその要素がどんな内容を持つかを宣言している。

 1行目は、(品名,個数)と記述している。この意味はそれほど難しいものではない。まず、括弧(( ))は、ひとかたまりの記述を1つにまとめるために使用されるものであり、表記上必要とされるだけのもので、何かの機能を示しているわけではない。中間に見えるカンマ記号(,)は、DTD上に書かれたとおりの順番にXML文書でも出現せよ、という意味を宣言している。つまり、(品名,個数)の意味は、品名要素の次に個数要素が出現する、ということを宣言している。もちろん、これは在庫要素の内容の宣言であるから、これは、在庫要素の子要素として、品名要素と個数要素が出現するということを示している。

 ここで注意すべきことは、カンマ記号(,)の役割である。これは、DTD上に書かれたとおりの順番にXML文書でも出現せよという機能を持っているが、たいへんに厳格な意味で使われる。つまり、(品名,個数)であれば、必ず品名要素、個数要素の順番に書かれている必要があり、どちらかが欠けていたり、順番が変わったりしてもいけない。また、どちらかの要素が複数書き込まれてもいけないし、品名要素、個数要素以外の要素があってもいけない(もちろん、DTDには省略を許すとか、複数記述を許すと言った構文を宣言する機能もあるのだが、それに関しては、カンマ記号ではない別の記号を用て記述する。これに関しては後で説明する)。

 さて、品名要素と個数要素の宣言には、他の要素名の代わりに、ただ#PCDATAとだけ書かれている。これは、ここに文字列データを書き込んでよいことを宣言している。#PCDATAは、そのための特別な名前である。これにより、品名要素の内容として、林檎と書くことが許され、個数要素の内容として、5という文字を書き込むことが許される、ということが宣言されているのである。

■DTDからXML文書をイメージする

 今一度、文字をxとyに置き換えただけのものと、DTDで書いたものを見比べてみよう。

文字をxとyに置き換えただけのもの:
<在庫>
  <品名>x</品名>
  <個数>y</個数>
</在庫>
DTDで書いたもの:
<!ELEMENT 在庫 (品名,個数)>
<!ELEMENT 品名 (#PCDATA)>
<!ELEMENT 個数 (#PCDATA)>

 後者から前者をイメージすることは詳細なルールを知らなければ、不可能だろう。ここまで直接的なイメージを変形して、抽象的な表記に置き換えてしまわなければ、必要な表現力が得られないということなのである。

 ちなみに、前者では、「xのところに品名を書いてね」と言えるが、後者の場合は品名も個数もどちらも#PCDATAとして表記されていて、区別することができない。そういう場合はどうすればよいのだろうか?

 答えは簡単である。「品名要素の内容に品名を書いてね」と要素の名前を明示すればよいのである。

DTDで表現できるバリエーション

 すでに述べた通り、在庫言語なら在庫できる製品が1種類しかないのはおかしい。ここはぜひとも、何種類でも在庫できるように拡張する必要がある。

■いくつでも要素を書けるようにする

 そこで、もう1つ、倉庫要素というものを導入し、倉庫要素の中には、いくつでも、好きな数だけの在庫要素を書いてよい、ということにしよう。例えば、一例として、以下のようなXML文書を書きたい、ということである。

<倉庫>
  <在庫>
    <品名>林檎</品名>
    <個数>5</個数>
  </在庫>
  <在庫>
    <品名>蜜柑</品名>
    <個数>7</個数>
  </在庫>
</倉庫>

 このルールをDTDで表現してみよう。結果はこうなる。

<!ELEMENT 倉庫 (在庫*)>
<!ELEMENT 在庫 (品名,個数)>
<!ELEMENT 品名 (#PCDATA)>
<!ELEMENT 個数 (#PCDATA)>

 2行目以降は前のサンプルと同じなので説明は省略する。ここでポイントなのは、倉庫要素の内容として書かれた在庫*という表記である。在庫とはもちろん、在庫要素をここに書いてよいことを示している。だが、その後に付いているアスタリスク記号(*)はいったい何を示しているのだろうか?

 実は、この記号は手前の要素が0回以上の任意回数繰り返して記述してよいということを示しているのである。子要素にある在庫要素は1個でもいいし、2個でもいいし、書かれていなくても(つまり0個でも)構わない。

■アスタリスク記号とプラス記号

 このアスタリスク記号には仲間がある。アスタリスク記号は0個以上の繰り返しという意味を持っているが、仲間達は、別のルールを機能として持っている。プラス記号(+)は、0回ではなく1回以上の繰り返しを行うという機能を持っている。つまり、プラス記号を使うと、何も書かないというのは不正ということになる。疑問符記号(?)は、0個または1個という指定を行う機能を持つ。つまり、書くか書かないか、どちらかを選択できるという意味を表現できる。もちろん、2個以上書くことは許されない。

 これらを使用することで、記述する内容に応じて長さが長くなるXML文書や、必要に応じて情報を書いたり、書かなかったりすることを許すXML文書のルールも書き下ろすことが可能になる。

まだあるDTDの表現バリエーション

 カンマ記号にも表現の仲間が存在する。

 例えば、以下のようなXML文書があるとする。

<番組>
  <主題歌/>
  <コマーシャル/>
  <本編前半/>
  <コマーシャル/>
  <本編後半/>
  <コマーシャル/>
  <副主題歌/>
  <次回予告/>
</番組>

 この場合、主題歌やコマーシャルの順番は決まっているからDTDを記述する場合はカンマ記号を使う(ここでは番組要素の宣言だけ書いている。他の要素の宣言も本当は必要である)。

<!ELEMET 番組 (主題歌,コマーシャル,本編前半,コマーシャル,本編後半,コマーシャル,副主題歌,次回予告)>

■どれか1つを選ぶバーチカルライン記号

 これに対して、順番を強制するのではなく、列挙された項目のどれか1つを選ぶという機能を持った記号がある。これがバーチカルライン記号"|"だ。多くの種類の選択肢があって、どれを選んでもよい場合などの表記に使用できる。例えば、料理要素の子要素として、ラーメン要素、つけ麺要素、冷やし中華要素のどれを書いてもよい、というルールは以下のように書ける。

<!ELEMENT 料理 (ラーメン|つけ麺|冷やし中華)>

 これは、具体的に言うと、以下の3文書はすべて正しいと宣言しているということである。

その1:
<料理>
 <ラーメン/>
</料理>
その2:
<料理>
 <つけ麺/>
</料理>
その3:
<料理>
 <冷やし中華/>
</料理>

 しかし、ラーメン要素を2個書いたり、ラーメン要素とつけ麺要素を連続して書いたりするのは間違いと見なされる。あくまで、どれか1つなのである。

 これらの記号は、複数組み合わせて活用することも可能である。例えば、「列挙した要素の中の1つを許す、ということを0回以上繰り返す」といった複合技も可能である。

DTDが活躍する場面とは

 DTDがどのようなものか、おおまかなイメージを掴んでいただけたと思う。

 このようにDTDは、かなり回りくどい変な表現方法を使う。書き方は分かるとしても、このような変な方法をあえて使うことに、どんなメリットがあるのだろうか? 普通に日本語で「料理の子要素は、ラーメン、つけ麺、冷やし中華のいずれか1つ」と書くほうが分かりやすいのではないだろうか?

■なぜDTDを使うのか

 これに対する答えは、日本語では十分ではないというものである。人間の使う言語は、とかく曖昧さが入り込みやすい。特に日本語は曖昧さにおいては世界に右に出るものはないと言われるほどである。例えば、「子要素にはAとBを記述することができる」と書くのは容易である。しかし、これがAの次に必ずBなのか、AまたはBのどちらかを書けるのか、読む者によって解釈に曖昧さが生じてしまう。

 このような曖昧さに、人間はある程度柔軟に対応できるかもしれない。だが、コンピュータはそうは行かない。何らかの業務用のソフトウェアは、要素の並び順に関して何かの前提を置いているかもしれない。そのような場合に、ルールの記述に曖昧さがあると、トラブルの元である。ソフトウェアが期待する並び順ではないデータを入力してしまうと、そこで業務が止まってしまうのである。

 このような問題を解決するためにはどうすればよいのか。それは、日本語のように曖昧さの入る言語ではなく、曖昧さが入らないように設計された専用の人工言語を使ってルールを記述するのである。この人工言語がいわゆるXMLのスキーマ言語である。

■スキーマ言語で、XML文書に書き間違いがないか判断できる

 専用の人工言語を利用することのメリットは、コンピュータにその内容を理解させることが容易である点だ。日本語をコンピュータに理解させるというのは、何十年も前から研究が続いているが、完全な理解にはほど遠いのが現状だ。そのため、日本語で書かれたルールをコンピュータに読ませて、XML文書がルール通りかどうか確認させるのは事実上不可能である。ところが、専用の人工言語ということなら、話は変わってくる。それをコンピュータに理解させるのは容易だし、もともと曖昧さがないので、中立公平にXML文書の正しさを判定させることができる。

 この中立公平というのは、コミュニケーションの場では大変に重要である。取り引きを行う際に、解釈の相違から喧嘩になったりしては話にならない。この種のスキーマ言語を用いることで、XML文書に書き間違いがないことを中立公平に判断することができることで、まったく技術的に縁のない組織間で、円滑なXML文書の伝達を実現することが可能になるのである。

まとめ:スキーマ言語はXML文書の交換に必要

 DTDは、いわゆるXMLのスキーマ言語の一種である。XMLのスキーマ言語は、人工言語である。XML文書の書き方のルールを曖昧さ無く表現することを目的とする。その重要な意図は、あるXML文書が正しい意図通りに記述されているかを、中立公平に判定することである。異なる組織間で、円滑にXML文書を交換するために重要な意味を持つものである。

 もし、自分で書いたXML文書を自分しか使わないのなら、DTDや他のスキーマ言語を覚える必要はないかもしれない。しかし、他者とXML文書を交換するのであれば、これらの言語を知っておく必要がある。それを知らなければ、自分が本当に正しいルールに沿ったXML文書を書いているかどうか、判断することができないからだ。また、逆も真である。他者から受け取ったXML文書が、ソフトウェアで処理できなかったときに、ソフトウェアが間違っているのかXML文書が間違っているのか、判断するためにはDTD等のスキーマ言語の知識が必要になる。

 一言で要約するなら、DTDはルールをコミュニケーションするのための言語だと言える。

 さて、今回は、DTDの意図を説明することを中心に行ったため、DTDの持つ多くの機能に触れずに終わってしまった。例えば、実体や属性に関する説明は何も行っていない。次回は、そのあたりの説明を行いたいと思う。

 それでは次回、また会おう。


Copyright © ITmedia, Inc. All Rights Reserved.

スポンサーからのお知らせPR

注目のテーマ

Microsoft & Windows最前線2025
AI for エンジニアリング
ローコード/ノーコード セントラル by @IT - ITエンジニアがビジネスの中心で活躍する組織へ
Cloud Native Central by @IT - スケーラブルな能力を組織に
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。