DTD(Document Type Definition)は、XML や HTML などの書き方を定義する定義ファイルです。DTD の正確な記述方法は少し面倒なものですが、ここでは、HTML の文法を定義する際に用いられている DTD に限定して、その定義内容を紹介します。
実際に、HTML4.01 の DTD の実例を見てみましょう。HTML4.01 には、Strict(厳密仕様)、Transitional(過渡的仕様)、Frameset(フレームセット)の 3つの DTD が定義されています。
HTML4.01 の DTD を読む際に必要な知識は、主に下記の 4つです。説明だけ読んでもよく分からないと思うので、先に 実例 を見たほうが分かりやすいかもしれません。
<!ELEMENT 要素名 開始タグ 終了タグ 子要素...>
要素名には HTML や BODY などの要素名を記述します。開始タグ、終了タグにはタグを省略可能かどうかを記述します。子要素にはその要素の子要素に関する情報を記述します。
形式 | 説明 |
---|---|
O O | 開始タグも終了タグも省略可能。(HTML、BODYなど) |
- O | 開始タグは省略不可能。終了タグは省略可能。(P、LI、IMG など) |
- - | 開始タグも終了タグも省略不可能。(B、STRONGなど) |
形式 | 説明 |
---|---|
A , B | カンマ。AとBがこの順番で。 |
A & B | AとBが順不同で。 |
A | B | AまたはB。 |
A* | 0個以上のA。 |
A+ | 1個以上のA。 |
A? | 0個または1個のA。 |
+A | 子や孫や曾孫などにAを0個以上記述可能。 |
-A | 子や孫や曾孫であっても、Aは記述できない。 |
EMPTY | 子要素を持たない。 |
<!ENTITY % エンティティ名 "内容...">
%エンティティ名; で参照されるエンティティを定義します。例えば、<!ENTITY % A "B, C, D"> と定義しているとすると、%A; と B, C, D は同じ意味であると解釈されるようになります。
<!ATTLIST 要素名 属性名1 属性型1; 省略時の値1 属性名2 属性型2; 省略時の値2 : : : >
各要素で使用可能な属性ついて定義します。
形式 | 説明 |
---|---|
(aaa|bbb) | aaa もしくは bbb。 |
CDATA | 文字列(Character Data)。改行(LF)は無視され、改行(CR)やタブ文字は 1つの空白文字に置換されます。属性値として使用する場合は、& や < や > を & < > と書き表す必要がありますが、ブラウザによって実装は様々のようです。style や script要素などの子要素として使用する場合は & などは & のまま解釈されます。この場合、</ のみが特殊な意味を持つ文字列となります。 |
#PCDATA | 解釈される文字列(Parsed CDATA)。< は タグの開始として解釈されるので、& や < や > は & < > と書き表す必要があります。 |
NUMBER | 数値。 |
ID | ID。識別子。最初の 1文字が英字(a~z、A~Z)で始まる、ハイフン(- )、アンダーバー(_ )、コロン(: )、ピリオド(. )を含む半角英数文字列。 |
NAME | 名前。書式は ID と同様です。 |
IDREF | ID への参照。例えば、id="abc" と定義されている場合、IDREF は #abc となる。 |
IDREFS | 複数の IDREF。それぞれはスペースで区切る。<th headers="#a #b #c"> など。 |
形式 | 説明 |
---|---|
#IMPLIED | 属性は省略可能で、省略時は環境に応じて適切な値が設定されます。 |
#REQUIRED | 属性必須です。省略時の値はありません。 |
#FIXED 値 | 属性は省略可能で、常に記述された値を持ちます。 |
値 | その属性の省略時の値を示します。 |
-- コメント --
-- と -- の間はすべてコメント(注釈)です。定義に関する補足説明などが記述されています。
では実際に、現在最も広く使用されている「HTML4.01 Transitional版」の DTD を読んでみましょう。
<!ELEMENT HTML O O (%html.content;) -- document root element -->
HTML要素がどんなものかを定義しています。HTML要素は、開始タグを省略可能(O
)、終了タグを省略可能(O
)です。%html.content; は、
<!ENTITY % html.content "HEAD, BODY">
と定義されていますので、上記の <!ELEMENT ...> は次のように展開されます。
<!ELEMENT HTML O O (HEAD, BODY) -- document root element -->
A, B は「A と B がこの順序で」を意味しますので、HTML要素の子要素には、HEAD要素、BODY要素がひとつずつ、この順序で現れることが分かります。
<!ATTLIST HTML %i18n; %version; > <!ENTITY % i18n "lang %LanguageCode; #IMPLIED dir (ltr|rtl) #IMPLIED" > <!ENTITY % LanguageCode "NAME"> <!ENTITY % version "version CDATA #FIXED '%HTML.Version;'"> <!ENTITY % HTML.Version "-//W3C//DTD HTML 4.01 Transitional//EN">
ENTITY による定義を展開すると次のようになります。
<!ATTLIST HTML lang NAME #IMPLIED dir (ltr|rtl) #IMPLIED version CDATA #FIXED '-//W3C//DTD HTML 4.01 Transitional//EN' >
HTML要素は、lang、dir、version という 3つの属性を持ちます。lang属性には名前を指定します。省略時の値はブラウザの実装などに応じて適切な値が選択されます。dir属性には、ltr もしくは rtl を指定します。version属性は、'-//W3C//DTD ...' という固定値を持ちます。
<!ELEMENT HEAD O O (%head.content;) +(%head.misc;)> <!ENTITY % head.content "TITLE & ISINDEX? & BASE?"> <!ENTITY % head.misc "SCRIPT|STYLE|META|LINK|OBJECT">
HEAD要素は、開始タグも終了タグも省略可能で、1つの TITLE要素、0個か1個の ISINDEX要素、0個か1個の BASE要素を順不同で子要素として持ち、加えて、子、孫、曾孫・・・要素として SCRIPT、STYLE、META、LINK、OBJECT要素を 0個以上記述することができることを意味します。
<!ELEMENT BODY O O (%flow;)* +(INS|DEL) -- document body -->
BODY要素は、開始タグも終了タグも省略可能で、子要素として 0個以上の %flow; を持ちます。また、子・孫・曾孫・・・要素として 0個以上のINS要素や DEL要素を持ちます。%flow; は、ブロック要素とインライン要素(後述)の総称です。
<!ELEMENT BODY O O (%block;|SCRIPT)+ +(INS|DEL) -- document body -->
HTML4.01 Strict での BODY要素の定義は、Transitional のものと少し異なります。BODY要素の子要素には、SCRIPT を除くインライン要素を記述することができません。つまり、HTML4.01 Strict では、<body>~</body> の間にいきなり文章や <img> などを記述することはできません。
<!ENTITY % block "P | BLOCKQUOTE | FORM | ...略..."> <!ENTITY % inline "#PCDATA | %fontstyle; | %phrase; | ...略..."> <!ENTITY % flow "%block; | %inline;"> <!ENTITY % fontstyle "TT | I | B | U | S | ...略..."> <!ENTITY % phrase "EM | STRONG | DFN | CODE | ...略...>
%block; はブロック要素(通常、前後に改行がはいるもの)、%inline; はインライン要素(通常、前後に改行が入らないもの)、%flow; はブロック要素とインライン要素の総称を意味します。
<!ELEMENT (%fontstyle;|%phrase;) - - (%inline;)*>
TT や I などのフォントスタイル要素や、EM や STRONG などのフレーズ要素は、子要素として 0個以上のインライン要素を持ちます。つまり、これらの要素は DIV や TABLE などのブロック要素を子要素として包含することはできません。
<!ELEMENT DIV - - (%flow;)* -- generic language ... --> <!ELEMENT CENTER - - (%flow;)* -- shorthand for DIV ... --> <!ELEMENT BLOCKQUOTE - - (%flow;)* -- long quotation --> <!ELEMENT P - O (%inline;)* -- paragraph --> <!ELEMENT ADDRESS - - ((%inline;)|P)* -- information on author -->
DIV、CENTER、BLOCKQUOTE要素は、子要素にインライン要素もブロック要素も記述することができますが、P要素の子要素にはインライン要素しか記述することができません。ADDRESS要素はインライン要素とP要素のみ記述できるようです。なにかこだわりがあるのでしょうね。
HTML4.01 Frameset に関しては、定義の大半が Transitional の DTD の中に記述されています。下記のような記述の部分に囲まれた部分が Frameset 用の DTD だと解釈してください。
<![ %HTML.Frameset; [ : ]]>
HTML4.01 Strict の DTD の抜粋です。属性の定義については割愛しています。強調 部分は、Transitional と差異があることを示します。
<!ELEMENT HTML O O (%html.content;)> <!ELEMENT HEAD O O (%head.content;) +(%head.misc;)> <!ELEMENT BODY O O (%block;|SCRIPT)+ +(INS|DEL)> <!ENTITY % html.content "HEAD, BODY"> <!ENTITY % head.content "TITLE & BASE?"> <!ENTITY % head.misc "SCRIPT|STYLE|META|LINK|OBJECT">
<!ELEMENT TITLE - - (#PCDATA) -(%head.misc;)> <!ELEMENT BASE - O EMPTY> <!ELEMENT META - O EMPTY> <!ELEMENT STYLE - - %StyleSheet> <!ELEMENT SCRIPT - - %Script;> <!ELEMENT NOSCRIPT - - (%block;)+>
<!ENTITY % flow "%block; | %inline;"> <!ELEMENT (INS|DEL) - - (%flow;)*>
<!ENTITY % block "P | %heading; | %list; | %preformatted; | DL | DIV | NOSCRIPT | BLOCKQUOTE | FORM | HR | TABLE | FIELDSET | ADDRESS"> <!ENTITY % heading "H1|H2|H3|H4|H5|H6"> <!ENTITY % preformatted "PRE"> <!ELEMENT HR - O EMPTY> <!ELEMENT DIV - - (%flow;)*> <!ELEMENT BLOCKQUOTE - - (%block;|SCRIPT)+> <!ELEMENT ADDRESS - - (%inline;)*> <!ELEMENT P - O (%inline;)*> <!ELEMENT (%heading;) - - (%inline;)*> <!ELEMENT PRE - - (%inline;)* -(%pre.exclusion;)> <!ENTITY % pre.exclusion "IMG|OBJECT|BIG|SMALL|SUB|SUP">
<!ENTITY % inline "#PCDATA | %fontstyle; | %phrase; | %special; | %formctrl;"> <!ENTITY % fontstyle "TT | I | B | BIG | SMALL"> <!ENTITY % phrase "EM | STRONG | DFN | CODE | SAMP | KBD | VAR | CITE | ABBR | ACRONYM" > <!ENTITY % special "A | IMG | OBJECT | BR | SCRIPT | MAP | Q | SUB | SUP | SPAN | BDO"> <!ELEMENT (%fontstyle;|%phrase;) - - (%inline;)*> <!ELEMENT (SUB|SUP) - - (%inline;)*> <!ELEMENT SPAN - - (%inline;)*> <!ELEMENT BDO - - (%inline;)*> <!ELEMENT A - - (%inline;)* -(A)> <!ELEMENT Q - - (%inline;)*> <!ELEMENT BR - O EMPTY> <!ELEMENT LINK - O EMPTY> <!ELEMENT IMG - O EMPTY> <!ELEMENT MAP - - ((%block;) | AREA)+> <!ELEMENT AREA - O EMPTY> <!ELEMENT OBJECT - - (PARAM | %flow;)*> <!ELEMENT PARAM - O EMPTY>
<!ENTITY % list "UL | OL"> <!ELEMENT UL - - (LI)+> <!ELEMENT OL - - (LI)+> <!ELEMENT LI - O (%flow;)*> <!ELEMENT DL - - (DT|DD)+> <!ELEMENT DT - O (%inline;)*> <!ELEMENT DD - O (%flow;)*>
<!ELEMENT TABLE - - (CAPTION?, (COL*|COLGROUP*), THEAD?, TFOOT?, TBODY+)> <!ELEMENT CAPTION - - (%inline;)*> <!ELEMENT THEAD - O (TR)+> <!ELEMENT TFOOT - O (TR)+> <!ELEMENT TBODY O O (TR)+> <!ELEMENT COLGROUP - O (COL)*> <!ELEMENT COL - O EMPTY> <!ELEMENT TR - O (TH|TD)+> <!ELEMENT (TH|TD) - O (%flow;)*>
<!ENTITY % formctrl "INPUT | SELECT | TEXTAREA | LABEL | BUTTON"> <!ELEMENT FORM - - (%block;|SCRIPT)+ -(FORM)> <!ELEMENT LABEL - - (%inline;)* -(LABEL)> <!ELEMENT INPUT - O EMPTY> <!ELEMENT SELECT - - (OPTGROUP|OPTION)+> <!ELEMENT OPTGROUP - - (OPTION)+> <!ELEMENT OPTION - O (#PCDATA)> <!ELEMENT TEXTAREA - - (#PCDATA)> <!ELEMENT FIELDSET - - (#PCDATA,LEGEND,(%flow;)*)> <!ELEMENT LEGEND - - (%inline;)*> <!ELEMENT BUTTON - - (%flow;)* -(A|%formctrl;|FORM|FIELDSET)>
HTML4.01 Transitional の DTD の抜粋です。属性の定義については割愛しています。強調 部分は、Strict に定義されていない、または差異があることを示します。
<!ELEMENT HTML O O (%html.content;)> <!ELEMENT HEAD O O (%head.content;) +(%head.misc;)> <!ELEMENT BODY O O (%flow;)* +(INS|DEL)> <!ENTITY % html.content "HEAD, BODY"> <!ENTITY % head.content "TITLE & ISINDEX? & BASE?"> <!ENTITY % head.misc "SCRIPT|STYLE|META|LINK|OBJECT">
<!ELEMENT TITLE - - (#PCDATA) -(%head.misc;)> <!ELEMENT BASE - O EMPTY> <!ELEMENT META - O EMPTY> <!ELEMENT STYLE - - %StyleSheet> <!ELEMENT SCRIPT - - %Script;> <!ELEMENT NOSCRIPT - - (%flow;)*> <!ELEMENT ISINDEX - O EMPTY>
<!ENTITY % flow "%block; | %inline;"> <!ELEMENT (INS|DEL) - - (%flow;)*>
<!ENTITY % block "P | %heading; | %list; | %preformatted; | DL | DIV | NOSCRIPT | BLOCKQUOTE | FORM | HR | TABLE | FIELDSET | ADDRESS | CENTER | NOFRAMES | ISINDEX"> <!ENTITY % heading "H1|H2|H3|H4|H5|H6"> <!ENTITY % preformatted "PRE"> <!ELEMENT HR - O EMPTY> <!ELEMENT DIV - - (%flow;)*> <!ELEMENT BLOCKQUOTE - - (%flow;)*> <!ELEMENT ADDRESS - - ((%inline;)|P)*> <!ELEMENT P - O (%inline;)*> <!ELEMENT (%heading;) - - (%inline;)*> <!ELEMENT PRE - - (%inline;)* -(%pre.exclusion;)> <!ENTITY % pre.exclusion "IMG|OBJECT|BIG|SMALL|SUB|SUP|APPLET|FONT|BASEFONT"> <!ELEMENT CENTER - - (%flow;)*>
<!ENTITY % inline "#PCDATA | %fontstyle; | %phrase; | %special; | %formctrl;"> <!ENTITY % fontstyle "TT | I | B | BIG | SMALL | U | S | STRIKE"> <!ENTITY % phrase "EM | STRONG | DFN | CODE | SAMP | KBD | VAR | CITE | ABBR | ACRONYM" > <!ENTITY % special "A | IMG | APPLET | OBJECT | FONT | BASEFONT | BR | SCRIPT | MAP | Q | SUB | SUP | SPAN | BDO | IFRAME"> <!ELEMENT (%fontstyle;|%phrase;) - - (%inline;)*> <!ELEMENT (SUB|SUP) - - (%inline;)*> <!ELEMENT SPAN - - (%inline;)*> <!ELEMENT BDO - - (%inline;)*> <!ELEMENT A - - (%inline;)* -(A)> <!ELEMENT Q - - (%inline;)*> <!ELEMENT BR - O EMPTY> <!ELEMENT LINK - O EMPTY> <!ELEMENT IMG - O EMPTY> <!ELEMENT MAP - - ((%block;) | AREA)+> <!ELEMENT AREA - O EMPTY> <!ELEMENT OBJECT - - (PARAM | %flow;)*> <!ELEMENT PARAM - O EMPTY> <!ELEMENT FONT - - (%inline;)*> <!ELEMENT BASEFONT - O EMPTY> <!ELEMENT APPLET - - (PARAM | %flow;)*>
<!ENTITY % list "UL | OL | DIR | MENU"> <!ELEMENT UL - - (LI)+> <!ELEMENT OL - - (LI)+> <!ELEMENT DIR - - (LI)+ -(%block;)> <!ELEMENT MENU - - (LI)+ -(%block;)> <!ELEMENT LI - O (%flow;)*> <!ELEMENT DL - - (DT|DD)+> <!ELEMENT DT - O (%inline;)*> <!ELEMENT DD - O (%flow;)*>
<!ELEMENT TABLE - - (CAPTION?, (COL*|COLGROUP*), THEAD?, TFOOT?, TBODY+)> <!ELEMENT CAPTION - - (%inline;)*> <!ELEMENT THEAD - O (TR)+> <!ELEMENT TFOOT - O (TR)+> <!ELEMENT TBODY O O (TR)+> <!ELEMENT COLGROUP - O (COL)*> <!ELEMENT COL - O EMPTY> <!ELEMENT TR - O (TH|TD)+> <!ELEMENT (TH|TD) - O (%flow;)*>
<!ENTITY % formctrl "INPUT | SELECT | TEXTAREA | LABEL | BUTTON"> <!ELEMENT FORM - - (%flow;)* -(FORM)> <!ELEMENT LABEL - - (%inline;)* -(LABEL)> <!ELEMENT INPUT - O EMPTY> <!ELEMENT SELECT - - (OPTGROUP|OPTION)+> <!ELEMENT OPTGROUP - - (OPTION)+> <!ELEMENT OPTION - O (#PCDATA)> <!ELEMENT TEXTAREA - - (#PCDATA)> <!ELEMENT FIELDSET - - (#PCDATA,LEGEND,(%flow;)*)> <!ELEMENT LEGEND - - (%inline;)*> <!ELEMENT BUTTON - - (%flow;)* -(A|%formctrl;|FORM|FIELDSET|ISINDEX|IFRAME)>
<!ELEMENT IFRAME - - (%flow;)*> <!ELEMENT NOFRAMES - - %noframes.content;> <!ENTITY % noframes.content "(%flow;)*">
HTML4.01 Frameset の DTD の抜粋です。属性の定義については割愛しています。強調 部分は、Transitional に定義されていない、または差異があることを示します。
<!ELEMENT HTML O O (%html.content;)> <!ENTITY % html.content "HEAD, FRAMESET"> <!ELEMENT FRAMESET - - ((FRAMESET|FRAME)+ & NOFRAMES?)> <!ELEMENT FRAME - O EMPTY> <!ELEMENT NOFRAMES - - %noframes.content;> <!ENTITY % noframes.content "(BODY) -(NOFRAMES)">