XHTML 1.0 の HTML 4 からの変更点

XHTML 1.0 の HTML4 からの変更点

[1] HTML 4XHTML 1.0 の違いは、 XHTML 1.0 勧告に書いてありますが、 そこに載っていない細かな違いもあったりします。 XHTML 1.0 FESE でも違いがいくつかありまして、そのうちの多くは HTML 4 により近づけるためのものです。

XHTML 1.0 仕様書は旧来の具象構文から XML への移行に伴う大きな変更点をつらつらと述べていますが、 細かな変更点は (意図しているのか間違いなのかわからないものも含めて) 明記されていなかったりもします。ということで、 HTML 4 DTD と XHTML 1.0 DTD の違いを調べてみました。 SE で HTML 4 式に復元している部分もある都合上、 FE から SE での変更点もあわせてまとめています。

(というわけで、この文章は、 HTML 4 から XHTML 1.0 でおおまかにどう変わったのかを知りたい方のお役には立ちません。 その辺は W3C の仕様書がわかりやすく解説していますから、そちらをお読みください。)

[37] 以降の検証で使用する DTD は、次の場所から入手できます。 Transitional/Frameset や FE/SE の別に触れずに XHTML 1.0 という場合は、両方の DTD で差がないことをあらわすとします。

なお、ここでは、実際上問題となる変更だけを取り上げています。 さほど影響のない引数実体の増減や DTD 中の宣言の順序など編集上の問題程度の変更は一々取り上げません。

データ型

[2] [%LanguageCode] 引数実体 LanguageCodeNAME から NMTOKEN になりました。 (XMLNAME がないため。)

[3] [%FrameTarget] 引数実体 FrameTargetCDATA から NMTOKEN になりました。 (後述の通り、 name 属性の型もあわせて変化しています。)

[12] [%Number] HTML 4 で属性の型が NUMBER とされていたところは悉く XHTML 1.0 では %Number; に置き換えられています。 XHTML 1.0 の引数実体 Number の実体値は CDATA です。 (NMTOKEN の方が元の宣言に近いと思うのですが...)

[14] [%UriList] 引数実体 UriList が XHTML 1.0 で追加されました。 object 要素の archive 属性の宣言が CDATA から %UriList; に変更されています。 (展開すれば結局 CDATA で変わりありませんが。)

属性

[4] [@xml:lang] 属性集合 %i18nxml:lang %LanguageCode; #IMPLIED が加わりました。 (要素型 html, head, title, meta, style, font, map, isindex, 属性集合 %attrs が影響を受けます。 属性集合 %attrs を通して要素型 link, noscript, noframes, body, div, p, h1, h2, h3, h4, h5, h6, ul, ol, menu, dir, li, dl, dt, dd, address, hr, pre, blockquote, center, ins, del, a, span, em, strong, dfn, code, samp, kbd, var, cite, abbr, acronym, q, sub, sup, tt, i, b, big, small], u, s, strike, object, img, area, form, label, input, select, optgroup, option, textarea, fieldset, legend, button, table, caption, colgroup, col, thead, tbody, tfoot, tr, th, td が影響を受けます。)

また、 bdo 要素型にも属性 xml:lang %LanguageCode; #IMPLIED が追加されています。

[5] [@data*] 引数実体 HTML.ReservedINCLUDE の時有効だった属性集合 %reserved がなくなりました。

つまり、 HTML 4 で予約とされていた WinIE 拡張の data* 系属性は XHTML 1.0 では使えません。 (要素型 div, span, object, input, select, textarea, button, table が影響を受けます。)

[18] [table/@datapagesize] table 要素型で HTML 4 の時には予約されていた datapagesize 属性が XHTML 1.0 にはありません。

[6] [html/@xmlns] html 要素型に属性 xmlns %URI; #FIXED 'http://www.w3.org/1999/xhtml' が加わりました。

[7] [html/@version] html 要素型の属性 version は削除されました。 (xmlns があるのでお役御免ということでしょうか。)

[8] [@id] XHTML 1.0 SE で、 要素型 html, head, title, base, meta, style, script に属性 id ID #IMPLIED が追加されました。

style 要素については、仕様書に xml-stylesheet 処理指令から参照する例が載っています <http://www.w3.org/TR/2002/REC-xhtml1-20020801/xhtml1-diff.html#C_14>。 (これに使うために style に追加されて、 他の要素型にもついでに追加したのでしょう。)

仕様書初版訂正票 <http://www.w3.org/2000/01/REC-xhtml1-20000126-errata/>Changes include the id attribute on all elements, which was missing in some elements. と言及がありました。

[9] [@xml:space] 要素型 style, script, pre に属性 xml:space (preserve) #FIXED 'preserve' が追加されました。

[11] [script/@event, script/@for] HTML 4 の script 要素型で予約されていた属性 event および for は XHTML 1.0 にはありません。

[10] [meta/@name, meta/@http-equiv の型] meta 要素型の name 属性および http-equiv 属性の型は、 HTML 4 では NAME でしたが、 XHTML 1.0 では CDATA です。 (NMTOKEN の方が HTML 4 に近いはず。 name はともかく、 http-equiv で文字種を拡大する必要性は考えられませんが...)

[12] [a/@name, object/@name, iframe/@name, applet/@name, img/@name, form/@name, frame/@name, map/@name] 要素型 a, object, iframe, applet, img, form, framename 属性の型は、 HTML 4 では CDATA でしたが、 XHTML 1.0 では NMTOKEN です。 (frame 要素型は Frameset DTD にのみ存在。)

map 要素の name 属性は HTML 4 と XHTML 1.0 Transitional DTD では CDATA で、 XHTML 1.0 Strict DTD と Frameset DTD では NMTOKEN です。 (Transitional DTD の修正し忘れか。)

[13] [bdo/@{%events}] bdo 要素型に属性集合 %events が追加されています。 (属性 onclick, ondblclick, onmousedown, onmouseup, onmouseover, onmousemove, onmouseout, onkeypress, onkeydown, onkeyup が追加されました。)

[15] [img/@border] img 要素型の border 属性の型は HTML 4 と XHTML 1.0 Frameset では %Pixels; ですが、 XHTML 1.0 Transitional では %Length; です。

[16] [map/@{%attrs}] map 要素型の属性のうち、 HTML 4 では属性集合 %attrs で宣言されていたものは XHTML 1.0 では展開されて属性集合 %i18n および %events ならびに属性 id, class, style, title で宣言しています。

map 要素型の id 属性は必須になりました。 (これが展開の理由。 本当は XML では属性定義の重複で最初のものが使われるのを利用すればこんなことしなくても済みますけどもね。)

[17] [input/@ismap] input 要素の ismap 属性が HTML 4 にはありますが、 XHTML 1.0 にはありません (漏れ?)。

[38] XHTML2 Working Group Teleconference -- 16 Sep 2009 ( 版) <http://www.w3.org/2009/09/16-xhtml-minutes.html#item04>
  • Steven: ... do you remember if this was deliberate?
  • Shane: I don't ... my gut feeling is that it's an omission

[18] [(th | td)/(@width | @height)] th 要素型および td 要素型の width 属性および height 属性の型は、 次の表のようになっています。

DTDTransitionalFrameset
HTML 4.01%Length;
XHTML 1.0 FE%Pixels;%Pixels;
XHTML 1.0 SE%Length;%Pixels;

XHTML 1.0 SE で HTML 4.01 にあわせようとして、 Frameset DTD を修正し忘れたのではないでしょうか。

[19] [@align=justify] XHTML 1.0 の属性 %TextAlign (HTML 4 では %align) の型が FE では (left|center|right) でしたが、 SE (と HTML 4) では (left|center|right|justify) です。 FE ではもれていたのを復活させただけでしょう。

この変更が影響する要素型は、 div, p, h1, h2, h3, h4, h5, h6 です。

内容模型

[23] [要素級] 要素級の変遷は次の通りです。

要素型HTML 4.01XHTML 1.0 FEXHTML 1.0 SE
em%phrase%phrase%phrase.basic
strong%phrase%phrase%phrase.basic
dfn%phrase%phrase%phrase.basic
code%phrase%phrase%phrase.basic
samp%phrase%phrase%phrase.basic
kbd%phrase%phrase%phrase.basic
var%phrase%phrase%phrase.basic
cite%phrase%phrase%phrase.basic
abbr%phrase%phrase%phrase.basic
acronym%phrase%phrase%phrase.basic
q%special%phrase%phrase.basic
sub%special%phrase%phrase.extra
sup%special%phrase%phrase.extra
tt%fontstyle%fontstyle%fontstyle.basic
i%fontstyle%fontstyle%fontstyle.basic
b%fontstyle%fontstyle%fontstyle.basic
u%fontstyle%fontstyle%fontstyle.basic
s%fontstyle%fontstyle%fontstyle.basic
strike%fontstyle%fontstyle%fontstyle.basic
big%fontstyle%fontstyle%fontstyle.extra
small%fontstyle%fontstyle%fontstyle.extra
font%special%fontstyle%fontstyle.extra
basefont%special%fontstyle%fontstyle.extra
span%special%special%special.basic
bdo%special%special%special.basic
br%special%special%special.basic
object%special%special%special.extra
applet%special%special%special.extra
img%special%special%special.extra
map%special%special%special.extra
iframe%special%special%special.extra
input%formctrl%inline.forms%inline.forms
select%formctrl%inline.forms%inline.forms
textarea%formctrl%inline.forms%inline.forms
label%formctrl%inline.forms%inline.forms
button%formctrl%inline.forms%inline.forms
a%special%inline%inline
%phrase%inline%inline%inline
%phrase.basic%phrase
%phrase.extra%phrase
%fontstyle%inline%inline%inline
%fontstyle.basic%fontstyle
%fontstyle.extra%fontstyle
%special%inline%inline%inline
%special.basic%special
%special.extra%special
%formctrl%inline
%inline.forms%inline%inline
%inline%flow%Inline, %Flow%Inline, %Flow
%Inline
#PCDATA%inline%Inline, %Flow%Inline, %Flow
要素型HTML 4.01XHTML 1.0 FEXHTML 1.0 SE
p%block%block%block
div%block%block%block
fieldset%block%block%block
table%block%block%block
isindex%block%block%block
pre%preformatted%blocktext%blocktext
blockquote%block%blocktext%blocktext
address%block%blocktext%blocktext
center%block%blocktext%blocktext
noframes%block%blocktext%blocktext
hr%block%blocktext%blocktext
ul%list%lists%lists
ol%list%lists%lists
dir%list%lists%lists
menu%list%lists%lists
dl%block%lists%lists
h1%heading%heading%heading
h2%heading%heading%heading
h3%heading%heading%heading
h4%heading%heading%heading
h5%heading%heading%heading
h6%heading%heading%heading
form%block%Block, %Flow%Block, %Flow
%heading%block%block%block
%list%block
%lists%block%block
%blocktext%block%block
%preformatted%block
%block%flow%Block, %Flow%Block, %Flow
%Block

注: noframes 要素型は XHTML 1.0 Frameset DTD では %blocktext に含まれません。

要素型HTML 4.01XHTML 1.0 FEXHTML 1.0 SE
insbody%misc%misc.inline
delbody%misc%misc.inline
script%special%misc%misc.inline
noscript%block%misc%misc
%misc%Inline, %Block, %Flow%Block, %Flow
%misc.inline%misc, %Inline
%flow
%Flow

insdel は、 HTML 4 DTD では body への添加要素となっていましたが、 XML DTD ではこれは表現できないので、 XHTML 1.0 DTD では %misc に入っています。 (HTML 4 DTD では ul などで両要素型が除外要素になっていない問題がありましたが、 XHTML 1.0 DTD では本来の意図通りになっています。)

%special%inline の要素であった script%misc.inline%misc%Inline, %Block に移動していますが、 Transitional で影響が出るのは map だけです。 Strict では更に noscript にも影響が及びます。 HTML 4 では script が子供として認められませんでしたが、 XHTML 1.0 では認められます。

noscript 要素の属する %misc は XHTML 1.0 FE では %Inline に含まれていましたが、 SE では含まれていません。 HTML 4 では noscript はブロック水準要素でしたから、 SE の方が正しい処置です。 FE で誤って noscript が認められていた要素型は次の通り: a, button, p, h1, h2, h3, h4, h5, h6, dt, span, bdo, em, strong, dfn, code, samp, kbd, var, cite, abbr, acornym, q, sub, sup, tt, i, b, u, s, strike, big, small, font, label, legend, caption

[20] [head] head 要素の内容模型は、 HTML 4 では <!ENTITY % head.content "TITLE & ISINDEX? & BASE?">, <!ENTITY % head.misc "SCRIPT|STYLE|META|LINK|OBJECT" -- repeatable head elements --> を踏まえて (%head.content;) +(%head.misc;) でした。

XHTML 1.0 では、 <!ENTITY % head.misc "(script|style|meta|link|object|isindex)*"> および (%head.misc;, ((title, %head.misc;, (base, %head.misc;)?) | (base, %head.misc;, (title, %head.misc;)))) と定義されています。

SGML の & (and) が XML では使えないので複雑になっていますが、実際上の変化は、 isindex の最大個数の変化です。 HTML 4 では高々1個だったのが、 XHTML 1.0 では任意個認められています。 (内容模型が必要以上に複雑になるより多少制限を緩めることにしたのでしょう。 実際 isindexbody 内に何個でも書けますから、 数を制限することに意味はないでしょうし。)

これを受けて title 要素型の宣言が HTML 4 の (#PCDATA) -(%head.misc;) から XHTML 1.0 の (#PCDATA) に変わっています。

[21] [script, style] script 要素型と style 要素型は、 HTML 4 では内容が %StyleSheet および %Script として定義されていました。いずれも実体は CDATA です。

XML では CDATA 内容が使えないので、いずれも (#PCDATA) に改められています。

[22] [table] table 要素型の内容模型が (CAPTION?, (COL*|COLGROUP*), THEAD?, TFOOT?, TBODY+) から (caption?, (col*|colgroup*), thead?, tfoot?, (tbody+|tr+)) に変わりました。つまり、 table 直下に tbody なしで tr を置けるようになりました。

[24] [noframes] Frameset DTD では、 noframes 要素型の内容は (BODY) -(NOFRAMES) と宣言されていましたが、 %Flow; に変わりました。つまり、 XHTML 1.0 Frameset DTD を使うときは、 noframes 要素に body タグを書くことはできません。

[25] [address] address 要素の内容は、 HTML 4 では ((%inline;)|P)* でしたが、 XHTML 1.0 FE で %Inline; (Strict DTD と同じ) になりました。しかし、 XHTML 1.0 SE で (#PCDATA | %inline; | %misc.inline; | p)* に修正されました。 (HTML 4 と同じでないのは XML DTD の表現能力のため。)

[26] [dir, menu] dir 要素と menu 要素の子の [CODE(HTMLe[li]] 要素の子孫にブロック水準要素を入れることは HTML 4 DTD では禁止されていましたが、 XML DTD では表現できないので、 XHTML 1.0 DTD では禁止されていません。

[27] [label] label 要素型の内容は、 HTML 4 DTD では (%inline;)* -(LABEL) でした。 XML DTD では除外要素指定ができないので、 XHTML 1.0 DTD では %Inline; と宣言されています。 直前の注釈宣言に Label elements shouldn't be nested. と書かれています。禁止から shouldn't に格下げ (格上げ?) になったようです。

XHTML 1.0 は仕様書の附属書 B で子孫要素として label 要素が出現することを禁じられています。

[28] [frameset] Frameset DTD の frameset 要素型は、 HTML 4 DTD では ((FRAMESET|FRAME)+ & NOFRAMES?) と宣言されていました。 XHTML 1.0 DTD では (frameset|frame|noframes)* です。

つまり、 HTML 4 では frameset または frame が最低1つ必要でしたが、 XHTML 1.0 DTD ではそうではありません。 noframes は高々1個でしたが、 XHTML 1.0 DTD では任意個認められます。しかも、 HTML 4 では frameset の最初か最後だったのか、 XHTML 1.0 DTD では他の要素の間にも置けることになります。

[29] [a] a 要素型の内容は、 (%inline;)* -(A) から %a.content; に変わりました。 %a.content は、 FE では (#PCDATA | %special; | %fontstyle; | %phrase; | %inline.forms; | %misc;)*、 SE では (#PCDATA | %special; | %fontstyle; | %phrase; | %inline.forms; | %misc.inline;)*" です。 実際の変化は、 FE で誤って認められていた noscript が SE で認められなくなっただけです。 XHTML 1.0 SE DTD の定義は、孫以下の要素が a になることを禁止していないほかは HTML 4 と同じ定義になります。

XHTML 1.0 では子孫要素として a 要素が出現することは仕様書の附属書 B で禁じられています。

[30] [pre] pre 要素型の内容は、 HTML 4 では (%inline;)* -(%pre.exclusion;) + <!ENTITY % pre.exclusion "IMG|OBJECT|APPLET|BIG|SMALL|SUB|SUP|FONT|BASEFONT"> と定義されていました。 XHTML 1.0 では %pre.content; でして、 FE では (#PCDATA | a | br | span | bdo | map | tt | i | b | u | s | %phrase; | %inline.forms;)*、 SE では (#PCDATA | a | %special.basic; | %fontstyle.basic; | %phrase.basic; | %inline.forms; | %misc.inline;)*、 です。

pre 要素の子要素に対する影響は次の通りです。

要素型HTML 4.01 Strict / Transitional / FramesetXHTML 1.0 FE Strict / Transitional / FramesetXHTML 1.0 SE Transitional / FramesetXHTML 1.0 SE Strict
%phrase.extra (sub, sup)××
strike×
その他 %fontstyle.basic (tt, i, b, u, s)
%fontstyle.extra (big, small, font, basefont)×××
map×
iframe××
その他 %special.extra (object, applet, img)××××
%misc.inline (ins, del, script)×
その他 %inline
その他××××

注: ○がついていても、 Strict DTD ではもともと使えない要素型もあります。

SE の変更のほとんどは FE の虫取りのようです。 mapiframe は HTML 4 の虫取りでしょう。

XHTML 1.0 では仕様書の附属書 B で子孫要素として img, object, big, small, sub, sup 要素が出現することを禁じられています。 附属書 B と DTD のどちらも normative ですので、矛盾があるのは困りものです。

[31] [form] form 要素は、 HTML 4 では (%flow;)* -(FORM) でした。 XHTML 1.0 では %form.content; で、 forms shouldn't be nested と注釈されています。

FE でも SE でも、 <!ENTITY % form.content "(#PCDATA | %block; | %inline; | %misc;)*"> です。子孫 form 以外は HTML 4 と同じです。

XHTML 1.0 は仕様書の附属書 B で子孫要素として form 要素が出現することを禁じられています。

[32] [button] button 要素は、 HTML 4 では (%flow;)* -(A|%formctrl;|FORM|ISINDEX|FIELDSET|IFRAME)、 XHTML 1.0 では %button.content; です。

<!ENTITY % button.content
   "(#PCDATA | p | %heading; | div | %lists; | %blocktext; |
      table | br | span | bdo | object | applet | img | map |
      %fontstyle; | %phrase; | %misc;)*">

ですから、子要素の制約としては HTML 4 と XHTML 1.0 は同じです。

XHTML 1.0 は仕様書の附属書 B で子孫要素として %inline.formctrl, fieldset, iframe, isindex の要素が出現することを禁じられています。

[33] [fieldset] fieldset 要素は、 HTML 4 では (#PCDATA,LEGEND,(%flow;)*) で、 #PCDATA is to solve the mixed content problem, per specification only whitespace is allowed there! という注釈がありました。 XHTML 1.0 では (#PCDATA | legend | %block; | form | %inline; | %misc;)* で、 if present should only be preceded by whitespace という注釈に、やはりトーンダウンしています。

XML DTD の制約で legend の位置と個数がまったく固定できなくなった他は両規格は同じです。

[34] [map] map 要素は、 HTML 4 では ((%block;) | AREA)+、 XHTML 1.0 では ((%block; | form | %misc;)+ | area+) です。

XHTML 1.0 では area とそれ以外の混在が認められなくなりました (なぜ?)。

[35] [object, applet] object 要素と applet 要素は HTML 4 では (PARAM | %flow;)*、 XHTML 1.0 では (#PCDATA | param | %block; | form | %inline; | %misc;)* です。

実際上の制約としてはどちらも同じです。

Strict DTD

[36] 本稿では Transitional DTD と Frameset DTD を扱ってきましたが、 簡単に Strict DTD にも触れておきましょう。 Transitional DTD の HTML 4.01 から XHTML 1.0 への変更点のうち Strict DTD と共通した部分のものは Strict DTD にも反映されています。そのほか、 param 要素型の name 属性が必須でなくなっています。 (Transitional DTD も HTML 4 Strict DTD も必須にしているので、 間違いかもしれませんが、 FE でも SE でも Strict DTD だけでは必須でありません。) HTML 4.01 には Strict でも存在する img 要素の name 属性は、 XHTML 1.0 にはありません。 (わざわざ注釈が付いていますから、意図したものでしょう。) form 要素の name 属性も、同じく HTML 4.01 にはあって XHTML 1.0 にありません。

Transitional DTD の XHTML 1.0 FE から SE への変更点のうち Strict DTD と共通した部分のものは Strict DTD にも反映されています。ただし、 %phrase.extra などの要素型級の細分化は独自に行われています。 (この影響が出るのは pre 要素だけで (というより pre 要素のための修正で)、それについては >>30 で扱っています。)

base 要素の href 属性は FE では省略可能でしたが、 (HTML 4 と) SE では必須です。 SE の大きな変更点はこれと id 属性 (>>8) です。簡単な変更ばかりなので、詳しくは diff をとってみてください。

[39] [body 内容モデル] HTML4 厳密DTD では body 要素にすることができませんでしたが、 XHTML 1.0 厳密DTD ではにできます。

[40] この種の違いは他にもあるかもです。。。