重要なのは、どんなタグの記法を用いれば、HTMLとの互換性を保ちつつXML(XHTML)としての機能を加えることができるのかということです。いくつかポイントを列挙します。
-
全てのタグ(要素タイプ名、属性名)は小文字で記述する
HTMLでは大文字と小文字は区別されませんでしたが、XMLではこれを区別するため、IMGとimgは別の要素タイプになってしまいます。XHTMLでは全ての要素タイプと属性は小文字で定義されたので、タグの記述にあたっても小文字を用いなければなりません(これまで書いたHTMLを書き直すのは大変…)。
また、属性名だけでなく、method="post"等のように、属性値がDTDで選択肢が定義されているものは、その通り記述する必要があります。これらもみな小文字で定義されているので、「タグは小文字で書く」と考えておくのがよいでしょう。
-
属性の値は必ず引用符で囲む
HTML(SGML)においては、値が数字など特定の値のみの場合は引用符を省略して width=100 のような記述が認められていましたが、XHTMLでは全ての属性値を引用符で囲んで width="100" のようにしなければなりません。
-
終了タグを省略しない
HTML(SGML)ではDTDの定義によっては終了タグを省略することができました。たとえば、リスト項目要素のLIの場合、
(誤りの例)
<ul>
<li>ある項目
</ul>
という具合に終了タグを省略することが認められ、それが一般的な書法となっていましたが、XMLではこれが認められません。必ず
(正しい例)
<ul>
<li>ある項目</li>
</ul>
のように終了タグを加えなければなりません。内容モデルを持たない空要素を除いて、全ての要素は開始タグと終了タグのペアで記述します。
-
空要素のタグは />で閉じる
また、HTMLのimg要素やbr要素のように、内容モデルを持たない空要素(HTMLでは開始タグしか使わないもの)は、XMLにおいては<br/>という具合に、タグを閉じるときに /> を使わなければなりません(空要素タグと呼ばれています)。ただし、この書式ではHTMLブラウザがタグを正しく認識できない可能性があるので、/ の前にスペースを置いて、 <br /> のように記述します。
-
ファイル内の位置を示すにはid属性を併記する
HTMLではファイル内の特定の位置へのリンクのためにname属性を使って
(誤りの例)
<a href="#foo">アンカーをクリックすると</a>
....
<a name="foo">ここにジャンプする</a>
という記述をしていましたが、XHTMLではファイル内部の位置を示す属性は id属性 になりました。従って、ジャンプ先は <a id="foo"> となるわけですが、このid属性をサポートしないブラウザもあるため、
(正しい例)
<a href="#foo">アンカーをクリックすると</a>
....
<a name="foo" id="foo">ここにジャンプする</a>
という具合に、name属性とid属性を同じ値で併記することが推奨されています(id属性そのものは、HTML 4.0から導入されています)。なお、XHTML1.1ではname属性は廃止され、id属性のみでフラグメントを示します。
-
&はあらゆるところで&と記述する
HTMLでも普通&は&と記述することになっていますが、XHTMLの場合、その用法が徹底していて、たとえばCGIを呼び出すためのURLでも
(誤りの例) <a href="/cgi-bin/myscript?name=kanzaki&score=100">
ではなく
(正しい例) <a href="/cgi-bin/myscript?name=kanzaki&score=100">
と記述する必要があります(本当はHTML 2.0の時からこの点も明記されていたが、ブラウザは&のままでもきちんと処理するように求められていたこともあり、これでも機能していた。cf. [RFC1866] 8.2.1. The form-urlencoded Media Type)。
-
属性の省略書式は使わない
HTMLでは、属性の名前と値が同じ場合に、属性名を記述せずに
(誤りの例) <input type="radio" name="bar" checked>
としていましたが、XHTMLではこれは認められず
(正しい例) <input type="radio" name="bar" checked="checked" />
と書かなければなりません。こうすると古い(新しいものでも一部)ブラウザでは正しく働かないことがありますが、それに対する解決策は示されていないようです。
-
head要素内のスクリプトやスタイルシートの注意
HTMLとは異なり、XHTMLにおいてはスタイルやスクリプトも#PCDATA(字句解析を受けるデータ)として定義されたため、< はタグの開始と見なされ、コメントした内容は無視されることになります。たとえばJavascriptで数値の比較をするような式を記述していると、XHTMLではエラーになり、スタイルシートを古いブラウザから隠すために
(誤りの例)
<style type="text/css">
<!--
p {color:red}
-->
</style>
のように記述していると、その定義は無視されてしまう可能性が高いとされています。解決策としては、外部ファイルにスタイルシートやスクリプトを記述することが推奨されています。
XHTMLファイル内にスクリプト要素を記述するときは、不等号などが問題を生じないように、その内部をCDATAセクションとして宣言しておきます。ただし、CDATAの宣言をそのまま書くとスクリプトのエラーになるので、宣言を//でスクリプトのコメントにしておきます。
(例)
<script type="text/javascript">
//<![CDATA[
function dmmy(){
//some script code
}
//]]>
</script>
このCDATAセクションの中に「HTMLのコメント宣言」に相当するものを書けば、XMLの処理には影響を与えませんが、古いブラウザがスクリプトのコードを表示しないようにする効果はあります。
-
言語コードの指定にxml:lang属性を用いる
XMLでは言語コードの指定にxml:lang属性を用いるので、HTMLとの互換性のためにlang属性と合わせて記述します。
(例) <p lang="fr" xml:lang="fr">Bonjour, monsieur</p>
XHTML 1.1ではlang属性は廃止され、xml:lang属性のみを記述します。
厳密にはもう少し細かい話もあるので、詳しく知りたい場合はW3Cの勧告[XHTML10]を参照。
XML宣言とencoding
XHTML1.0の仕様書[XHTML10]3.1.1 Strictly Conforming DocumentsではXML宣言について次のように述べています:
XHTML document authors are strongly encouraged to use XML declarations in all their documents. Such a declaration is required when the character encoding of the document is other than the default UTF-8 or UTF-16 and no encoding was determined by a higher-level protocol.
旧版[XHTML10-1]の仕様書では and no encoding...
以下の最後の部分がなかったため、「XHTMLでは文書の文字コードがUTF-8もしくはUTF-16でない場合はXML宣言が必須」といわれてきましたが、XHTML1.0 Second Edition[XHTML10-2]の仕様書C.9. Character Encodingでは
In order to portably present documents with specific character encodings, the best approach is to ensure that the web server provides the correct headers. If this is not possible, a document that wants to set its character encoding explicitly must include both the XML declaration an encoding declaration and a meta http-equiv statemen
と、サーバーのヘッダ情報を指定できない環境で文字コードを明示したい場合は、XML宣言とmeta要素の両方が必要であるとしています。ちなみにXMLの仕様書[XML1]では、4.3.3 Character Encoding in Entitiesにおいて次のように定められています:
In the absence of external character encoding information (such as MIME headers), parsed entities which are stored in an encoding other than UTF-8 or UTF-16 must begin with a text declaration (see 4.3.1 The Text Declaration) containing an encoding declaration...
つまり、HTTPヘッダなどで文字コード情報が送られない場合のみ、encoding宣言が必要だというわけです。
一部ブラウザとの互換性の問題点
Mac版のIE4.5はXML宣言を正しく理解できず、(おそらくデータをtext/plainとして扱って)ソースコードをそのまま表示してしまうという現象があります。文字コード情報をサーバー側で設定できるなら、XML宣言を省略するのが一番簡単です。
また、XSSI[SSI]の使える環境(Apacheのバージョン1.2以降は標準装備)なら、次のようにすることで比較的簡単にMacIE4.5のみXML宣言を出力しないようにすることが可能です。
(例)
<!--#if expr="$HTTP_USER_AGENT != /MSIE 4.5; Mac/" -->
<?xml version="1.0" encoding="Shift_JIS"?>
<!--#endif -->
<!DOCTYPE html
etc...
ここでは読みやすくするためにXSSI命令のあとで改行していますが、XML宣言の前に不正な改行が入ってしまうので、1,2行目は連続して記述する方がよいでしょう。
これらの対応が不可能な場合、ドキュメントの先頭に適当なコメントを置いておけば、Mac-IE4.5はデータがHTMLであると認識します。
(本来は正しくない例)
<!-- dummy comment -->
<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
etc...
これは厳密にはXMLの文法上誤りですが、実害は少ないので、Mac-IE4.5利用者にも表示できるようにするには一つの方法です。
〔補足〕Mac-IEの4.51ではこの状況は改善されて、基本的にはおかしなコメントなしでも正しく表示されるようですが、逆にディレクトリのデフォルトファイルとしてファイル名を省略して取得するときは、このコメントがあってもソースが表示されてしまいます。Mac-IE 5ではこれらの問題点は解消されています。
また、Windows版のIE5の場合は、コメントをXML宣言とhtml要素の間に置くと、文書をXMLとして解釈してしまいます。html要素の内部(開始タグ以降)であれば、問題なくHTMLとして解釈できるようです。