[1] HTML 4 と XHTML 1.0 の違いは、 XHTML 1.0 勧告に書いてありますが、 そこに載っていない細かな違いもあったりします。 XHTML 1.0 FE と SE でも違いがいくつかありまして、そのうちの多くは 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]
引数実体 LanguageCode
は NAME
から NMTOKEN
になりました。
(XML に NAME
がないため。)
[3] [%FrameTarget]
引数実体 FrameTarget
は CDATA
から 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]
属性集合 %i18n
に xml: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.Reserved
が INCLUDE
の時有効だった属性集合 %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
,
frame
の name
属性の型は、 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
にはありません (漏れ?)。
[18] [(th | td)/(@width | @height)]
th
要素型および td
要素型の
width
属性および height
属性の型は、
次の表のようになっています。
DTD | Transitional | Frameset |
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 ではもれていたのを復活させただけでしょう。
[23] [要素級] 要素級の変遷は次の通りです。
注: noframes
要素型は XHTML 1.0 Frameset DTD
では %blocktext
に含まれません。
要素型 | HTML 4.01 | XHTML 1.0 FE | XHTML 1.0 SE |
ins | body | %misc | %misc.inline |
del | body | %misc | %misc.inline |
script | %special | %misc | %misc.inline |
noscript | %block | %misc | %misc |
%misc | − | %Inline , %Block , %Flow | %Block , %Flow |
%misc.inline | − | − | %misc , %Inline |
%flow | − | − | |
%Flow | − |
ins
と del
は、 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 では任意個認められています。
(内容模型が必要以上に複雑になるより多少制限を緩めることにしたのでしょう。
実際 isindex
は body
内に何個でも書けますから、
数を制限することに意味はないでしょうし。)
これを受けて 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 / Frameset | XHTML 1.0 FE Strict / Transitional / Frameset | XHTML 1.0 SE Transitional / Frameset | XHTML 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 の虫取りのようです。 map
と iframe
は 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;)*
です。
実際上の制約としてはどちらも同じです。
[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 では空にできます。