DTDは初めて見ると複雑で嫌になるかもしれませんが、読むのはそれほど難しくありません。
DTDについては、HTML Structure - SGMLについてをご覧下さい。
以下は、HTML4.01のDTDです。
Frameset DTDは、ほぼTransitional DTDと同一です。以下の点が違います。
これを知っておけば十分ですが、Frameset DTDの読み方が知りたい方は、Frameset DTDの読み方をご覧下さい。
要素宣言です。使用する要素名、タグの省略、内容型などを宣言します。以下のように宣言します。
<!ELEMENT 要素名 タグの省略 (内容型)>
では実際に、要素宣言を見てみましょう。ここでは、DL要素を例として使用します。
<!ELEMENT DL - - (DT|DD)+ -- definition list -->
まず、DLで、要素名をDLとして宣言します。
次の「- -」ですが、これは前者が開始タグ、後者が終了タグを表します。「-」が指定されているときは、タグの省略は許可されません。省略が許可されるときは「O(大文字のオー)」が指定されます。
内容型の(DT|DD)+ですが、これは外側から見ていきます。まず括弧に「+」がついているので、「括弧内のものを一つ以上」という意味になります。そして中のDT|DD」は「DT要素、またはDD要素」という意味になります。
その後ろの「-- definition list --」は、コメントです。よくコメントを表すときに「<!-- コメント -->」としますが、SGMLでは、マーク宣言内に「--」が現れると、次に現れる「--」までをコメントとする決まりになっています。このコメント部分には、この要素の意味などが書かれていることが多いです。
これを全て読むと、「DL要素は、タグの省略は許可されず、内容にDT要素、またはDD要素を一つ以上含む。」ということになります。
内容型の宣言では、いくつかの記号が使われます。まずは、それを理解する必要があります。
| 記号 | 意味 |
|---|---|
| ? | 直前の要素が、0回または1回出現する。 |
| + | 直前の要素が、1回以上出現する。 |
| * | 直前の要素が、0回以上出現する。(なくてもよいということ) |
| +() | 直後の要素が出現してもよい。 |
| -() | 直後の要素が出現してはならない。 |
| , | 列挙される要素が、列挙された順序通りに出現する。 |
| | | 列挙されたようそのうち、どれかが出現する。 |
| & | 列挙された要素が出現するが、順序は問わない。 |
| EMPTY | 内容を持ってはならない。(空要素) |
| #PCDATA | テキストデータ。(#PCDATA) |
PCDATAに#がついていますが、これについては#PCDATAをご覧下さい。
次に、これら記号を使った例文を見てみましょう。
| 内容型 | 意味 |
|---|---|
| x | xが必ず1回だけ出現する。 |
| x? | xが0回、または1回出現する。 |
| x+ | xが1回以上出現する。 |
| x* | xが0回以上出現する。(なくてもよい) |
| +(x) | xが出現してもよい。 |
| -(x) | xが出現してはならない。 |
| x , y | xとyがこの順序で出現する。 |
| x | y | xまたはyが必ず出現する。 |
| x & y | xとyが必ず出現するが、順序は問わない。 |
属性リスト宣言です。要素が持つことのできる属性を列挙します。以下のように宣言します。
<!ATTLIST 要素名
属性名 属性値 属性値の初期値
>
実際には、改行はなくてもいいのですが、見にくいので普通は改行して列挙します。
属性値は、特定の文字列や実体定義、データ形式のいずれかを指定します。
まず、以下のFORM要素の例をご覧下さい。
<!ATTLIST FORM
%attrs; -- %coreattrs, %i18n, %events --
action %URI; #REQUIRED -- server-side form handler --
method (GET|POST) GET -- HTTP method used to submit the form--
enctype %ContentType; "application/x-www-form-urlencoded"
accept %ContentTypes; #IMPLIED -- list of MIME types for file upload --
name CDATA #IMPLIED -- name of form for scripting --
onsubmit %Script; #IMPLIED -- the form was submitted --
onreset %Script; #IMPLIED -- the form was reset --
accept-charset %Charsets; #IMPLIED -- list of supported charsets --
>
属性値の初期値に指定されているもので、例えばmethod属性は、指定しない場合はGETと見なされることを示します。enctype属性も同様に、指定しない場合は"application/x-www-form-urlencoded"と見なされることを示します。
先頭に#がついている物は#PCDATAと同様に、予約名であることを示します。以下にその意味を示します。
初期値がないことを示します。
これが指定されている属性は、属性自体が省略できますが、省略した場合の挙動については、各ウェブブラウザに任されます。
これ以外の初期値が指定されているものは、属性自体が省略できるわけではなく、省略しても何らかの初期値が与えられることになります。
その属性が省略不可の必須属性であることを示します。
これが指定されている属性以外は、一応全て省略可能です。
属性値に、ただ一つ属性名と全く同じ文字列を取り得る属性のことを、特に論理型属性と呼びます。
例えば、OPTION要素の、selected属性がこれにあたります。
selected (selected) #IMPLIED
見ての通り、属性名がselectedで、属性値にはselectedただ一つのみが取り得ます。
実体宣言です。DTD内部でのみ使用される実体のことを、特にパラメータ実体と呼びます。任意の要素や属性の別名を定義するものです。以下のように宣言します。
<!ENTITY 実体名 "実体">
DTD内部でのみ使用するパラメータ実体の場合は、実体名の前に%を付加し、参照は%実体名;として参照します。
では、実際に宣言を見てみましょう。
<!ENTITY % heading "H1|H2|H3|H4|H5|H6">
実体名が「heading」で、実体がH1-H6要素です。こうすることによって、要素宣言が簡潔になります。
<!ELEMENT (%heading;) - - (%inline;)* -- heading -->
このようにすることで、一度にH1からH6までを、要素宣言しました。%inline;についても、どこかで定義されているわけです。
ちなみに、パラメータ実体と違い、DTD外で使用する実体のことを一般実体と呼びます。一般実体では、宣言時に%は付加されず、参照時は&実体名;とすることで参照します。
これはいわゆる文字参照です。
「よくわかんねーよ」、と言う感じかもしれませんが、要はとりあえず「<!ELEMENT 知りたい要素名」でDTD内を検索すれば知りたいものが出てきます。もしかしたら出てこないかもしれませんから、その場合は要素名そのもので検索してみましょう。どこかのENTITY宣言で実体定義されているかもしれません(先のH1-H6要素のように)。
DTDで見ることは、基本的にELEMENT宣言の内容型とATTLIST宣言です。「この要素は中になにを含むことができるのだろう」というときや「どんな属性があってその属性はどんな値をもてるのだろう」という時など、その都度見ていけばいいでしょう。一度に覚える必要はありません。