Latest topics > 独自の文書型宣言を含めつつエラーを出さない方法(XHTML 1.1でXMLとして他の名前空間の要素を組み合わせて使いたい人向けの話)
宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。 以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能!
独自の文書型宣言を含めつつエラーを出さない方法(XHTML 1.1でXMLとして他の名前空間の要素を組み合わせて使いたい人向けの話) - Mar 17, 2010
僕はXHTMLのルビ(小さな字で読み仮名をふったりするアレ)を使いたくてXHTML 1.1を選択してるんですが、過去にXHTML2で検討されてたl要素(パラグラフより細かい単位の「行」を示すための物)やiframeやなんかをどうしても埋め込みたくなって、しかしそのせいでバリデータでエラーが出てしまうのも嫌だったので、見よう見まねで頑張って独自の文書型宣言を書いてみたんですよ。いつやったのか忘れたけど、結構前に。
<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" [
<!ENTITY % XLINK.xmlns.attrib "xmlns:xhtml2 CDATA #FIXED 'http://www.w3.org/2002/06/xhtml2'">
<!ENTITY % Inline.extra "| xhtml2:l | iframe">
<!ELEMENT xhtml2:l (#PCDATA|br|span|em|strong|dfn|code|samp|kbd|var|cite|abbr|acronym|q|sub|sup|bdo|a|img|map|object|input|select|textarea|label|button|ruby|ins|del|script|noscript|xhtml2:l)*>
<!ATTLIST xhtml2:l
id ID #IMPLIED
class CDATA #IMPLIED
style CDATA #IMPLIED
title CDATA #IMPLIED>
<!ELEMENT iframe (#PCDATA|br|span|em|strong|dfn|code|samp|kbd|var|cite|abbr|acronym|q|sub|sup|bdo|a|img|map|object|input|select|textarea|label|button|ruby|ins|del|script|noscript|xhtml2:l)*>
<!ATTLIST iframe
id ID #IMPLIED
class CDATA #IMPLIED
style CDATA #IMPLIED
title CDATA #IMPLIED
longdesc CDATA #IMPLIED
src CDATA #IMPLIED
frameborder ( 1 | 0 ) '1'
marginwidth CDATA #IMPLIED
marginheight CDATA #IMPLIED
scrolling ( yes | no | auto ) 'auto'
height CDATA #IMPLIED
width CDATA #IMPLIED
>
]>
CGIを使ってIEにはこの文書型宣言を出さないようにしてますが、FirefoxとかChromeとかでトップページあたりを開いてソースを見れば、こういうのが頭にくっついてるのが分かると思います。
で、バリデータ的にはこれでvalidになったのでめでたしめでたしだったんですが、GeckoのDTDパーサ部分にバグがあるらしくて、この文書型宣言を正しく解釈してくれないんですよね。最後の]>
ではなくその前の>
の部分で文書型宣言が終わったものと見なされてしまうせいで、Firefoxでこのサイトのページを開くと、ページの頭に謎の]>
という文字列がくっついてしまう状態になってたのです。表示が崩れるのが嫌だったので、この]>
がテキストノードとしてページの頭に存在してる時は動的に削除するようなJavaScriptを書いて、長らくごまかしてました。
そしたら先日、W3CのHTML5のルビに関する議論の中で紹介されてたXHTMLルビサポートのページを見たという方(Leif Halvard Silliさん)がメールを下さいまして、以下のようなハックを使えばページの頭に謎の]>
が出てくる事を防げるよ、と教えてくれたんです。
<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" [
<!ENTITY % XLINK.xmlns.attrib "xmlns:xhtml2 CDATA #FIXED 'http://www.w3.org/2002/06/xhtml2'">
<!ENTITY % Inline.extra "| xhtml2:l | iframe">
<!ELEMENT xhtml2:l (#PCDATA|br|span|em|strong|dfn|code|samp|kbd|var|cite|abbr|acronym|q|sub|sup|bdo|a|img|map|object|input|select|textarea|label|button|ruby|ins|del|script|noscript|xhtml2:l)*>
<!ATTLIST xhtml2:l
id ID #IMPLIED
class CDATA #IMPLIED
style CDATA #IMPLIED
title CDATA #IMPLIED>
<!ELEMENT iframe (#PCDATA|br|span|em|strong|dfn|code|samp|kbd|var|cite|abbr|acronym|q|sub|sup|bdo|a|img|map|object|input|select|textarea|label|button|ruby|ins|del|script|noscript|xhtml2:l)*>
<!ATTLIST iframe
id ID #IMPLIED
class CDATA #IMPLIED
style CDATA #IMPLIED
title CDATA #IMPLIED
longdesc CDATA #IMPLIED
src CDATA #IMPLIED
frameborder ( 1 | 0 ) '1'
marginwidth CDATA #IMPLIED
marginheight CDATA #IMPLIED
scrolling ( yes | no | auto ) 'auto'
height CDATA #IMPLIED
width CDATA #IMPLIED
>
<?parser-hack ><!-- ?>
]>
<!--><?!-->
強調箇所がそのハック。処理命令(PHPのコード片を埋め込んだりするのに使うのと同じ奴)の記法でコメントとして解釈できる文字列を埋め込んで、問題の部分を無視させるという物のようです。バリデータに通しても、これでもvalidです。素晴らしいです。
同じような事をやってる酔狂な人がもしいたら役立てて欲しいと思ったので、氏に許可を得てエントリにさせて頂きました。Thanks a lot, Leif!
文法的な解釈
何故これがvalidなのかも考えてみよう。
<?parser-hack ><!-- ?>
- この行は、これ自体で1つの処理命令となる。
- 処理命令は <?ターゲット名 任意のUnicode文字?> という書式なので、これはあくまで「
><!--
という内容」を含んだ処理命令として解釈される。
- 処理命令は <?ターゲット名 任意のUnicode文字?> という書式なので、これはあくまで「
- 文書型宣言の定義では、
[
から]
までの間に登場しうる内容として処理命令も含まれている。そして、上記の箇所は一つの完結した処理命令である。よって、文書型宣言中に登場しても何ら問題ない。
<!--><?!-->
- この行は、「
><?!
という内容」を含んだコメントと解釈される。
という具合で文法的には何も問題ないので、W3Cのバリデータはこれをvalidと判断する。きちんとXMLパーサを実装しているブラウザ上でも同様です。
Geckoの解釈
一方、Geckoの解釈はどうか。これは「ソースを表示」での色分けを見るとよく分かる。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" [
Geckoはまず、この部分だけで完結した文書型宣言と認識する。「[
」で終わりと判断したのではなくて、その次の <!ENTITY
が来た時点で「あ、もう文書型宣言は終わってたのね」と見なしてるようだ。
<!ENTITY ~>
<!ELEMENT ~>
<!ATTLIST ~>
この辺はすべて、それぞれ別々の宣言として解釈されている。という事で、
]>
何もハックをしない場合はこの部分だけが取り残されてしまって、Gecko的にはこれが「XML的には不正だけどSGML的にはアリ」なテキストノードとして扱われて、ゴミとして表示されてしまうわけだ。
では、ハック有りの場合はどうなるか。
<?parser-hack ><!-- ?>
]>
<!--><?!-->
Geckoはこれを3つのノードとして解釈している。
<?parser-hack >
まずGeckoは、これを1つの処理命令と判断する。XMLの仕様では ?>
が来るまで処理命令の終わりにはならないんだけど、Geckoのパーサは >
で処理命令が終わったものと見なしてしまう。
<!-- ?>
]>
<!-->
これは当然1つのコメントになる。
<?!-->
最後、これも <?
から >
までで1つの処理命令と見なされる。
という事で、ハック有りの時はどの文字もテキストノードとして取り残されずに済むので、画面上は何もゴミが表示されずに済む。
こんなのよく考えるなー、と、読み解いてみて改めて感心しました。
- « すべて彼女のために
- Main
- ツリー型タブのサイドバーをAll-in-One Sidebarと連携させられないの?(I want the tree of tabs to be shown in the sidebar.) »
Comments/Trackbacks
TrackBack ping me at
の末尾に2020年11月30日時点の日本の首相のファミリーネーム(ローマ字で回答)を繋げて下さい。例えば「noda」なら、「2010-03-17_parser-hack.trackbacknoda」です。これは機械的なトラックバックスパムを防止するための措置です。
Post a comment
writeback message: Ready to post a comment.
カテゴリ一覧
- 全てのエントリ (2478)
- blosxom (9)
- チェックリスト (9)
- dream (1)
- イベント (71)
- 生活 (154)
- その他 (9)
- モテ・非モテ・恋愛・自己承認 (160)
- Mozilla (791)
- 拡張機能 (305)
- backtoowner (2)
- bfthumbnail (3)
- bookmarks2pane (3)
- ctxextensions (2)
- foxsplitter (4)
- greasemonkey (1)
- gsuggest (4)
- historycounter (1)
- informationaltab (2)
- multipletab (6)
- mystickies (1)
- observelipboard (1)
- openbookmarkintab (1)
- rewindforward (4)
- rubysupport (2)
- searchcache (4)
- secondsearch (5)
- splitbrowser (7)
- tabcatalog (2)
- tabextensions (2)
- tabkiller (1)
- textlink (11)
- textshadow (7)
- treestyletab (57)
- undotab (1)
- uxu (8)
- viewsourceintab (1)
- xulmigemo (50)
- extensions (1)
- treestyletab (1)
- fennec (3)
- Firefox (77)
- jetpack (2)
- その他 (135)
- Thunderbird (10)
- work (1)
- XUL (257)
- extensions (1)
- textlink (1)
- treestyletab (1)
- 拡張機能 (305)
- 絵 (63)
- moezilla (7)
- 立体物 (24)
- レビュー・感想 (205)
- 風景 (9)
- ソフトウェア (36)
- chrome (1)
- gimp (1)
- illustrator (1)
- inkscape (1)
- nsis (3)
- OpenOffice.org (1)
- safari (1)
- sai (2)
- システム再構築 (73)
- 出来事・雑感 (766)
- トリビア・ムダ知識 (22)
- 服装とか (6)
- Web技術 (69)
- CSS (3)
- JavaScript (31)
- jsdeferred (1)
- prototype.js (3)
- ruby (2)
- XML (1)
最近のコメント
- Windows 10で「デスクトップの解像度」と「アクティブな信号解像度」が一致しない現象が発生したときの解決方法
- 11/22 16:44 by えいぎょー
- 06/15 21:20 by えあ
- 06/17 21:22 by no name
- 言葉が通じない同士で対話するのが面白い「ヘテロゲニア リンギスティコ」、言葉は通じるのに対話ができないのが辛い「魚頭さんと袋さん」
- 03/21 17:50 by マチカ
- 表現の自由と表現規制に関する自分のスタンスの再確認
- 05/02 11:37 by れっか
- 05/02 20:20 by Piro
- 11/29 09:39 by p
- 激しくDISられた時は「この人は視野狭窄に陥っているオタクなんだ」と思うと辛くなくなる、というライフハック
- 08/18 10:21 by みら
- 08/18 21:28 by lovepotion
- 11/29 09:09 by p
- WSLでフォルダーを作るとWindowsでNTFSなパーティションでも大文字小文字が区別される落とし穴がある
- 12/30 21:25 by no name
- JPOP王道進行とウンコ曲と「違いが分かる人」
- 10/20 20:08 from yamj diary
- Gmail宛にメールを片っ端から転送すると元のアドレスのドメインが受信拒否されるようになることがある、という問題
- 05/18 18:43 from ひがきの日記
- 自信ありそうげな人が妬ましいし羨ましい
- 12/10 12:45 from 自分、無粋ですから
- 「元のソフトウェアがGPLだから公開できない」という誤解について
- 02/04 08:40 from 練炭ブログ
- Ubuntu 9.10からUbuntu 10.04にアップグレードした
- 08/10 12:39 from 日々想うこと