Wrong HTML - DTDを読む

DTDとは?

HTMLは国際規格ISO8879に基づいたSGML(Standard Generalized Markup Language)の応用ですので、SGML宣言とDTD(文書型定義)によって定義されています。DTDは名前の通り文書の構造やその規則(例えば要素同士の入れ子関係や要素がどのような属性を持つか)などが定義されているのです。

DTDの読み方、定義のしかたを理解しておけばXMLなどの導入にも困らないで済むでしょうし、間違った知識を持ってしまうことも防げます。

HTML 4.01のDTD

Body要素の定義を読み解いてみる

タグの省略

Body要素の定義は

<!ELEMENT BODY O O (%block;|SCRIPT)+ +(INS|DEL) -- document body -->

となっていますね。!ELEMENT BODY でBodyという要素の定義であることがわかります。続くO O ですが、これは開始、終了タグが省略可能かどうかを表していて、この定義の場合「O O」(OmitのOです)となっているので開始、終了タグ共に省略が可能です。逆に省略ができない場合は「- -」となります。またMetaなどの終了タグが省略されなければならない要素は- O EMPTYというようにEMPTYキーワードが付いています。

要素の内容

次に(%block;|SCRIPT)+ とありますが、これはその要素の内容を示していて、%blockとあるのはパラメータ実体というものでDTDのマクロのようなものです。!ENTITYから始まる形で定義してありますので探してみると

<!ENTITY % block
"P | %heading; | %list; | %preformatted; | DL | DIV | NOSCRIPT |
BLOCKQUOTE | FORM | HR | TABLE | FIELDSET | ADDRESS">

と書いてあります。これは「!ENTITY」は実体の定義であること、%に続く文字列がその名前、「|(or演算子)」で区切られているものがその実体が参照している値です。このことから要素Bodyの内容には"P | %heading; | %list; | %preformatted; | DL | DIV | NOSCRIPT | BLOCKQUOTE | FORM | HR | TABLE | FIELDSET | ADDRESS | SCRIPT"が指定できる、と宣言していると分かります。

内容の出現

内容をもう一度見てみると( )で囲まれ、+が付いていますが、これは( )で囲まれたグループがどのように出現するかを示しています。その指定法は

A
Aが1回のみ出現しなければならない
A+
Aが1回以上出現しなければならない
A*
Aが0回以上出現してもよい
A?
Aが0回または1回出現しなければならない
+(A)
Aが出現してもよい
-(A)
Aは出現してはならない
A,B
指定された順番で出現しなければならない
A | B
AとBのどちらかが出現しなければならない、AとBが同時に出現してはならない
A & B
AとBが必要だが、順序は問わない

とこのようになっています。要素Bodyの内容には「%blockかSCRIPTが1回以上出現」し、「DSLかINSが出現してもよい」ということになります。

また、最後の「-- document body --」のように「--」で囲まれた文はコメントとして扱われます。

属性の定義

Body要素の属性の定義は

<!ATTLIST BODY
%attrs; -- %coreattrs, %i18n, %events --
onload %Script; #IMPLIED -- the document has been loaded --
onunload %Script; #IMPLIED -- the document has been removed --
>

となっています。!ATTLISTで属性の定義であること、それに続く名前でどの要素の属性かを示しています。まず「onload %Script;」を見てみましょう。あまり説明することもないのですが、これは「属性名 属性値」で並んでいるのがわかりますね。続く#IMPLIEDの部分は、省略されたときの指定で、#IMPLIEDはその属性の指定は任意であり、省略された場合はUAによってデフォルト値が指定されることを示しています。このキーワードが#REQUIREDだった場合には属性の省略はできません。また属性名にパラメータ実体が指定されている時はその参照先に従います。

その他の要素も見てみる

今度はButton要素を見てみることにします。要素の定義は

<!ELEMENT BUTTON - -
(%flow;)* -(A|%formctrl;|FORM|FIELDSET)
-- push button -->

となっています。開始、終了タグ共に省略不可になっていて、内容は%flowが0回以上出現してもよく、「A|%formctrl;|FORM|FIELDSET」は出現できないことになっています。要素の宣言は先ほどまでの内容と変わりませんね。では、属性はどうでしょう。

<!ATTLIST BUTTON
%attrs; -- %coreattrs, %i18n, %events --
name CDATA #IMPLIED
value CDATA #IMPLIED -- sent to server when submitted --
type (button|submit|reset) submit -- for use as form button --
disabled (disabled) #IMPLIED -- unavailable in this context --
tabindex NUMBER #IMPLIED -- position in tabbing order --
accesskey %Character; #IMPLIED -- accessibility key character --
onfocus %Script; #IMPLIED -- the element got the focus --
onblur %Script; #IMPLIED -- the element lost the focus --
%reserved; -- reserved for possible future use --
>

ここで見ていただきたいのは属性値です。type属性の場合、属性値として「button|submit|reset」を指定でき、省略時にはsubmitになるようですね。ではCDATANUMBERというのはなんでしょう?これらはデータ型と言い、どのような特性を持つ内容かを表します。CDATAは任意の文字列、NUMBERは数字ということになります。

ここではDTDの読み方を簡単に説明しました。この内容だけでいくらかDTDは読み書きができるとは思うのですが、もっと詳しく知りたい方はSGML、またはXMLなどの専門サイトなどを訪問してみてください。