鳩丸よもやま話

bakera.jp > 鳩丸よもやま話 > SGMLの注釈宣言

SGMLの注釈宣言

コメントとは

通常、プログラムを書くときには、ソースに「コメントを入れる」という作業が行われます。これは、その部分で何をしているのか、何のためにこのような処理が入っているのか、と言ったようなことがすぐに分かるようにするためです。これによって、別の人がプログラムを修正したり、後になって書き直したりするときに、すぐに内容を理解することができるようになります。

※もちろんコメントの内容にもよりけりで、どうしようもないコメントというのもありますが。

HTML や XML の文書にも、それと同じようにコメントを挿入することができます。

マーク宣言の中のコメント

SGML では、マーク宣言の中に任意のコメントを書くことが出来るようになっています。DTD や SGML宣言の中に解説を入れておくことで、見通しの良い宣言文になるわけです。

コメントは、コメント区切り子 COM によって表現されます。通常、COM は "--" という文字列です。コメントの開始と終了は、どちらもこの区切り子によって表されます。

マーク宣言の中で空白文字の出現が許されている所には、COM で区切ってコメントを挿入することが出来ます。たとえば、

<!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.01//EN">

というおなじみの文書型宣言には、

<!DOCTYPE --comment1-- HTML --comment2-- PUBLIC --comment3--
"-//W3C//DTD HTML 4.01//EN" --comment4-->

と、四ヶ所にコメントを挿入することが可能です。

※もっとも、SGMLの文法として正しいからと言って、コメントが常に正しく解釈されるとは限りません。たとえば Another HTML-lint は、上記のようなコメント入りの文書型宣言をうまく認識できません。HTML の文書型宣言にコメントなどを入れるべきではないでしょう。

良くあるのは、

<!ELEMENT BAKERA - - (%flow;)* -- comments -->

のように、DTD の要素宣言や属性宣言の中に書かれたコメントです。これで、どんなものを宣言しているのかを書き留めておくわけですね。

なお、コメントの中には < > & などの文字をそのまま記すことが出来ます。コメント中にこれらが現れても、SGML のマークとはみなされず、単なるコメントの一部として解釈されます。

文書インスタンスの中のコメント

基本的に、コメントというものはマーク宣言の中でしか有効ではありません。たとえば、HTML の文書インスタンスに、地の文として -- コメント -- などと書いたとしても、これはそのまま表示されてしまいます。

文書中にコメントを入れるためには、注釈宣言というものを使います。これは通常、以下のような形をしています。

<!-- comments -->

マーク宣言の姿をしていますが、意味のある宣言ではなく、コメントだけが含まれています。コメントは無視されますから、宣言内容は空っぽだということになります。ですから何の効果も持ちません。HTML文書中に意味のあるマーク宣言を書き込むわけには行きませんから、意味を持たない空っぽの宣言を使って、コメントを書き込むわけです。

※なお、注釈宣言はマーク宣言の一種であってタグではありませんので、これを「コメントタグ」などと呼ぶと意味が通じません。IE独自拡張の <comment> というタグはコメントタグと呼んで間違いないと思いますが、それは一般的な HTML ではありません。

注釈宣言のヴァリエーション

注釈宣言はコメントだけで構成されていなければなりません。意味ある宣言はパーサーを混乱させます。

SGML では、以下のようなコメントの書き方ができます。

<!--コメント-->
<!--コメントの後ろに空白-- >
<!--複数行にま-
たがる-
コメント-->
<!--複数の-- --コメント-- --です-->
<!--<SAMP>タグのコメントアウトもできます。</SAMP>-->

それぞれのコメントの後ろには空白や改行の挿入が許されます。もちろん、コメントの中身に空白が含まれていても構いませんし、< > などもそのまま入れられます。また、一つの注釈宣言は複数のコメントを持つことが出来ます。

コメントの中身が空だったり、コメントの数が零でも構いませんので、以下のようなものも正しいコメントです。

<!---->
<!-------------------->
<!-- -- >
<!>

ただし、<! とコメントとの間に空白を挿入することは許されていません。<! の後ろには、ただちにコメントもしくは > が出現しなくてはなりません。

※空白が入ったりすると、<! がマーク宣言開始区切り子とみなされなくなります。これは他のマーク宣言でも同様で、たとえば <! DOCTYPE ……のように空白を入れてはいけません。また、当然ながら < と ! の間にも空白は許されません。

そんなわけで、以下のようなものは誤りです。

<! --コメント-- >
<!
--改行してからコメント-->
<! >

いずれも、よけいな空白や改行が入ってしまっています。

良くある間違い

注釈宣言を良く理解していないためか、コメントのつもりで変なものを書いている例が結構あります。

本当は表示されてしまう文字列

コメントのつもりで謎の文字列を書いてしまっている人がいます。たとえば、以下のように。

<!コメントのつもり>
<!-ハイフンが足りないよ!->
<!->

これらにはそもそもコメント区切り子 -- がないので、<!> の間は注釈宣言とはみなされません。

※<! には「制約」があります。<! がマーク宣言開始区切り子として認識されるのは、その直後に名前開始文字、コメント区切り子、宣言部分集合開始区切り子、マーク宣言終了区切り子のいずれかが来た時だけです。つまり、これらのいずれにも該当しないものが <! の直後に来ると、それはマーク宣言開始区切り子としては認識されません。< の後ろの ! は GI でもありませんから、< が開始タグ開始区切り子とみなされることもありません。従って単に "<!" という文字データが書かれているものとみなされます。

また、

<!test>
<![適当な文字]>

のようなものは、<! がマーク宣言開始区切り子とみなされるものの、謎の文字列が現れるために宣言として解釈することが出来ません。要するに不正なマーク宣言とみなされます。

もっとも、たいていの WWW ブラウザは SGML のマーク区間などの構文解釈をしないので、単に <! ~ > の間を無視します。その結果として、これらはコメントのように振る舞うかも知れません。

閉じないコメント

注釈宣言の中には複数のコメントを入れることが出来ます。ところが、単に <!--> の中が無視されると思っている人がいるらしく、閉じないコメントを書いている例があります。

<!--コメント開始……>
地の文?
……

これがどういうふうに構文解釈されるのか、考えてみましょう。

まず、<! があります。後ろは -- ですから、これはマーク宣言開始区切り子とみなされ、以降がマーク宣言であるとみなされます。続いて -- がコメント区切り子です。以降はコメントとなります。

さて、ここで重要なのは、コメントの中には < や > をそのまま書くことが出来て、それらは SGML のマークとは解釈されないということです。コメントの中で解釈されるのは、コメント終了を示すコメント区切り子 -- だけです。

つまり、-- 以降、-- が現れるまでがコメントとみなされ、無視されることになります。

ここで上記の例に戻りますと、コメント区切り子 -- によってコメントが開始され、そのあとに > が出現していますが、これはマーク宣言終了区切り子とはみなされません。単なるコメントの一部とみなされます。-- が現れてコメントが閉じられるまで、> などは区切り子として機能しないのです。

結局、最後まで -- が出てこなければ、最後までコメントとみなされ、無視されることになります。

以下のようなコメントを考えてみましょう。

<!--あいたっ (>_<)-- >

これは正しい注釈宣言で、全てコメントとして無視されます。-- が出てきたところでコメントが終わり、そのあとの > で宣言が閉じます。

ところが、WWW ブラウザの中には、> の直前でコメントが終了すると判断してしまうものがあります(親切のつもりだろうけどよけいなお世話)。そして、正しいはずのコメントをうまく処理できなかったりします。たとえば以下のようにコメントを書いてみます。

ぶった<!--あいたっ (>_<)-- >ぶたれた

コメント部分が無視されて「ぶったぶたれた」、となるのが期待される挙動ですが、 実際には "_<)-- >" を表示してしまうブラウザが数多く存在します。不正なコメントに対する救済措置が裏目に出ているのです。

ハイフン書きすぎ

今の例に似ていますが、むやみにハイフンを書いている例があります。以下のようなものです。

<!---------------------->

ハイフンを数えると 22 個あります。これは、空のコメントが五つあって、その後ろにコメント区切り子があるということですから、最後の > はコメントで、区切り子ではありません。以降がずっとコメントとみなされます。

また、このような例もあります。

<!--コメントの中に--が入ると-->

これも似たようなものです。「が入ると」という文字列はコメントではなく、不正なマーク宣言となります。そのあとにまたコメントが開始していますので、> はコメントとみなされ、以降ずっとコメントとみなされてしまいます。

<!---ハイフン三つ-->

これは正しいコメントです。コメント区切り子の後ろに余分なハイフンが一つありますが、これは区切り子ではなくコメントとみなされますから問題ありません。ただし、以下のようにしてしまうと……。

<!---ハイフン三つずつ--->

後ろのハイフン三つは、前半の二つでコメント区切り子とみなされます。そこでコメントは終わりますから、最後のハイフンはコメントではありません。不正なマーク宣言です。

XML では?

ここまで述べたのは SGML のコメントの書き方です。XML では、コメントの書式は以下のように定義されています。

[15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'

以上、Extensible Markup Language (XML) 1.0 (Second Edition) 2.5 Comments より

SGML 的な言い方をすれば、一つの注釈宣言の中には一つのコメントだけが許されるようになっています。一つの注釈宣言に複数のコメントを入れることは禁止されています。もちろんコメントの中に "--" が入っているようなものも許されず、well-formed になりません。

コメントと解釈されない場合

<!-- --> を書いても、それがコメントとして扱われない場合もあります。CDATA区間の中や、内容モデルCDATA あるいは RCDATA であるような要素の中では、<!-- などを書いても単なる文字列とみなされるだけです。

※属性値も RCDATA としてパースされることになっていますので同様です。もっとも、属性値の中にコメントを入れようとする人はいないでしょうが。

特に注意が必要なのは、内容モデルが CDATA であるような要素です。HTML4 では、script要素 style要素の内容モデルが CDATA になっています。たとえば、このように書くと……

<script type="text/javascript">
<!--
……スクリプト……
//-->
</script>

script要素の中身はコメントではなく、単なる文字列でしかありません。<!-- や --> も含めた文字列がそのままスクリプトとして解釈されます。

※そしてスクリプトエンジンの側では <!-- で始まる行を Javascript のコメントとして扱い、無視します。HTML のコメントとして扱われるわけではありません。

ですから、実は以下のような記述も正当です。

<script type="text/javascript">
<!--
<!--
<!--
<!--
<!--
<!--
</script>

これらはそもそも HTML のコメントではありませんから、コメント開始とコメント終了の整合性も関係ありません。

style要素についても同様です。

<style type="text/css">
<!--
body{display:none;}
-->
</style>

これも HTML のコメントではありません。<!-- や --> も含めた文字列がそのままスタイルシートとして解釈されます。そして CSS では <!-- や --> の出現が文法上許されていて、それらは単に無視されることになっています。

しかし、XHTML では script要素 style要素の内容モデルが #PCDATA なので注意が必要です。

<script type="text/javascript">
<!--
……スクリプト……
//-->
</script>

と書くと、これは XHTML ではコメントとみなされますので、srcipt要素の中身が空なのと同じことです。スクリプトエンジンには何も渡りません。

※……となるのが正しいのですが、ブラウザは融通を利かせてくれているかもしれません。

そもそも、HTML の仕様としては script要素 style要素の内容を <!-- --> で括る必要はありません。括っているのは、それらの要素を解釈しない古いブラウザで内容が表示されないようにするための配慮です。

しかし、現時点でそのような配慮が必要なブラウザがどれだけあるのでしょうか。script要素内を <!-- --> で括るのも、そろそろやめてしまっても良いのではないかと思いますが……。

最近の日記

関わった本など