Media type と HTML lint について

ここに検索等で来た方へ。この文書はlintでなんで100点取れないの?という人に説明するときのために個人的にメモしたもので、lintで100点を取ることを推奨するものではありません。逆に多少の風刺が入っています。また、個人的なメモであるので内容については吟味していません。あくまで参考程度にお読みください。(22 May 2004, 自分でしたgoogle検索でここがかかってしまい追記。)

application/xhtml+xmlを.htaccessで設定

W3C XHTML Media Typesによれば、XHTML 1.1のmediatypeはapplication/xhtml+xmlが最も適切であり次にapplication/xml,text/xmlとされている。

また、http-equivでmediatypeを指定する方法は後方互換のためであり、xmlでは薦められていない。本来http-equivの内容はサーバーで解釈されてヘッダに付加されなければならないが、そのような処理はサーバーの負担になるため実際には行なわれていない。

しかし、lintではxhtml1.1のmediatypeがapplication/xhtml+xmlでなければ警告がなされる。もっとも望ましい方法は、.htaccessを使って確実にmediatypeを指定する方法である。.htaccessの内容をAddType "application/xhtml+xml; charset=UTF-8" .htmlとする。

このようにしてlintで100点をとれるようにしたxhtml文書の例

また、標準モード対策にxml宣言を抜いた例では、

6: line 1: XHTML1.1 では XML宣言をすることが強く求められています。 → 解説 21
5: line 23: XHTML1.1 では XML宣言中に encoding 指定をしましょう。 → 解説 137

と二点の警告がなされ、89点になる。.htaccessでcharset=UTF-8としているのでXML宣言中でencoding指定をしなくても文字化けすることはない。W3Cの仕様の翻訳によれば、

この例ではXML宣言が組み込まれていることに注意してほしい。上記のようなXML宣言は、すべてのXML文書に必須というわけではない。XHTML文書の制作者は、すべての文書でXML宣言を使うよう強く奨励される。文書のキャラクタエンコーディングがデフォルトの UTF-8 か UTF-16 以外のものであるときは、そうした宣言は必須である。

とあり、encodingがUTF-8 か UTF-16であるときにはXML宣言は推奨されるものの、必須ではないことがわかる。

しかしこのURLを各UAで閲覧すると、Operaやモジラでは正しく扱う事ができるが、IEでは致命的なことにapplication/xhtml+xmlというmediatypeはxml文書として扱われずにダウンロードになってしまう。

application/xmlかtext/xmlを.htaccessで設定

これでは現実的といえないので、次に望ましいmediatypeである、application/xmlかtext/xmlを考える。.htaccessの内容をAddType "application/xml; charset=UTF-8" .htmlとする。

application/xmlにした例また、XML無しのもの

これはlintではhtmlと解釈されずにチェックさえもなされない。Operaやモジラでは正しく閲覧できるが、IEではDTDの解釈でエラーが出る。これはDTDに問題があるのではなく、IEに問題があるためだ。詳しくはMSXML で XHTML ファイルを読み込む際の注意点が参考になる。

結局、IEが正しく処理できないために、mediatypeをtext/htmlとせざるをえない。これはW3Cではすべきではない(SHOULD NOT)とされているのだが、仕方ない。現在公開されているweb上でIEで閲覧できるxhtmlのmediatypeは全て実際にはSHOULD NOTであるはずのtext/htmlになっているのである。(<meta http-equiv="Content-Type" content="application/xhtml+xml;・・・としていてもサーバーでこれを解釈していないので飾りでしかない。実際にはtext/htmlとして投げられてる筈で、そうなければIEでは見られない)

仕方ないのでtext/htmlを.htaccessで設定

仕方ないのでtext/htmlにした例また、XML無しのもの

lintでは

1: line 24: HTTPレスポンスヘッダに指定されているメディアタイプ text/html は XHTML1.1 には指定しないようにしましょう。 → 解説 143

と減点され、93点になる。しかし見る事ができないのではどうしようもないのでtext/htmlにする以外の選択肢は無い。標準モード対策でXML宣言を抜いた例では87点となる。

前述の通りUTF-8ではXML宣言は必須ではないのでわかってやっているなら許容範囲かと思う。次にXML宣言を抜くとなるとどうやって確実に文字コードを指定するかが問題になるが(XMLのデフォルトコードはUTF-8であるがUAがそれを前提に文書を解釈するかはtext/htmlで投げてしまっている以上、文書がXMLとは扱われないのでこれを保証できない。)この例では.htaccessにてcharset=UTF-8としているのでhttp-equivで文字コードを指定しなくても化ける事は無い筈だ。

text/htmlでかつ.htaccessで文字コードを指定しない場合

.htaccessで文字コードを指定しない場合を考える。

XML宣言あり XML宣言無し

この例では前述のパターンに加え、

4: line 6: <head>?</head> 内に <meta http-equiv="content-type" content="?" /> が含まれていません。 → 解説 128

というエラーが追加され、点数はそれぞれ89点, 78点となる。またこのパターンではUAで文字化けしない保証が全く無い。

text/htmlでかつhttp-equivで文字コードを指定

最後に.htaccessで文字コードを指定しないが、http-equivで指定する方法を考える。

http-equivでapplication/xhtml+xmlを指定
XML宣言あり
XML宣言無し

: line 5: HTTPレスポンスヘッダに指定されているメディアタイプは `text/html` ですが、<meta> に指定されているのは `application/xhtml+xml` です。 → 解説 142

と警告され86点, 75点。

http-equivでtext/htmlを指定
XML宣言あり
XML宣言無し

1: line 5: に指定されているメディアタイプ text/html は XHTML1.1 には指定しないようにしましょう。 → 解説 143 と警告され88点, 77点。

まとめ

標準モードに拘るとなると、XML宣言中に文字コードの指定が出来ないので、IEで閲覧する事が出来て、文字化けしない方法は結局

  1. httpヘッダ内でcharset=UTF-8とする(.htaccessで設定する)ことでhttp-equivを省く。
  2. http-equivでcharsetを指定する / メディアタイプはtext/html。
  3. http-equivでcharsetを指定する / メディアタイプはapplication/xhtml+xml。

このどれかということになる。

3では気持ちだけapplication/xhtml+xmlということになる。一般的なサーバーではいちいちこれを解釈してapplication/xhtml+xmlとして投げることをしないので、実際にはtext/htmlで投げられる。したがってカッコだけつけていてもIEでも閲覧できる。しかし、このずれがlintでは警告される。そもそもhttp-equivはxhtmlでは薦められない方法なのにここでカッコつけてもどうかと言った感じである。しかし.htaccessかhttp-equivで文字コードを指定しなければ標準モード対策でXML宣言を抜いた時に文字化けしない保証が無い。

2は、カッコつけることは諦める方法である。実際のメディアタイプとhttp-equivのずれが無いのである意味こちらの方が上品ではある。

1は、http-equivという過去の手段をきっぱり諦めることができるので最もスマートな方法だろう。しかし.htaccessの効果が及ぶ範囲を考慮しないと、サイト内で複数の文字コードがある場合にうまく機能しない可能性がある。