SGML宣言とは、その文書で SGML のどのような機構を利用し、どのような文字を使い、どのような記号でマーク付けを行うのかなどを定義するものです。
たとえば、HTML ではどんな文字が使えるのか、省略タグや短縮タグは利用できるのか、属性値の長さに制限はあるのか、などといったことはすべてこの SGML宣言の中で規定されています。
SGML宣言はマーク宣言開始区切り子 "<!" で始まり、SGML というキーワード、次いで "ISO 8879:1986" という文字列の順に記述されます。これは、この文書が 1986年の ISO 8879 の規格に従うことを意味します。
以下、文書文字集合、容量集合、具象構文範囲、具象構文、機構使用、応用特有情報がこの順で記述されます。
"CHARSET" で始まる部分です。SGML文書で使う文字を定義します。BASESET と DESCSET を含みます。
SGML 文書内で使う文字を含む文字集合を指定します。たとえば HTML4.0 では
BASESET "ISO Registration Number 177//CHARSET
ISO/IEC 10646-1:1993 UCS-4 with
implementation level 3//ESC 2/5 2/15 4/6"
となっていて、ISO10646 の文字集合に含まれる文字を利用することになっています。
SGML文書内で使用する文字番号が、それぞれ BASESET のどの文字に対応するのかを規定します。これは次のような書式になっています。
先頭文字番号 文字個数 対応文字番号 先頭文字番号 文字個数 対応文字番号 ……
先頭文字番号というのは文字集合中の何番目の文字であるかを示し、そこから示した文字個数ぶんだけの文字の対応関係を定義します。たとえば
57344 1056768 57344
と書かれているような場合、57344番から 1114112番までの 1056768個の文字は、ISO10646 の 57344番から 1114112番にそれぞれ対応します。要するに、ISO10646 の文字番号ををそのまま扱う、と定義されているのだと考えて構いません。
特殊な場合として、
1 1 3 2 1 2 3 1 1
のように定義することも出来ます。この場合、1番の文字を3番に、3番の文字1番に対応させています。要するに 1番の文字と 3番の文字を入れ替えているわけですが、こんな使い方をすることはほとんどありません。
なお、
0 9 UNUSED
と書いてあれば、文字番号 0 から 8 までの 9 個の文字は BASESET の特定の文字には対応せずに、"UNUSED" とされます。UNUSED とされた文字は意味を持ちません。制御コードに該当する部分を BASESET に対応させてしまうと制御コードとして機能してしまうので、"UNUSED" として制御コードとしての機能を無効化したりします。
他にもキーワードで意味が与えられる場合があり得ます。BASESET に含まれない特殊な文字を使うときなど。ただ、これはあまり使われません。
"CAPACITY" で始まる部分です。文書の容量や複雑さの上限を設定します。実体参照や要素の定義できる数の上限などが規定されているのですが、通常は気にしなくて良いでしょう。
CAPACITY に続いて "SGMLREF" と書かれていますが、これは、「以下に指定がない場合には規格に定められた既定値を使う」という程度の意味です。このキーワードは必須で、省略できません。
CAPACITY は以下のようなものを含むことができます。指定を省略すると規格参照とみなされます。
規格参照ではいずれの値も 35000 となります。
"SCOPE" で始まる部分です。具象構文が文書インスタンス(いわゆる本文)のみに適用されるのか、DTD を含む文書全体に適用するのかを規定します。
SCOPE DOCUMENT となっていれば文書全体に、SCOPE INSTANCE となっていれば文書インスタンスのみに適用されます。
"SYNTAX" で始まる部分で、区切り子に使う文字、名前に使える文字、名前字句の長さなど、文法に関する様々なものを規定します。SGML宣言の中でも最も重要な部分と言って良いでしょう。
回避文字(shunned character)を示します。回避文字とは、制御文字として扱われる可能性があるため、データとして記述してはならないものです(もちろん制御文字として使うことはあるでしょうけれど)。
SHUNCHAR NONE と書かれていれば回避文字はありません。CONTROLS と書かれていれば、文字集合の中で制御文字とされているものすべてが回避文字であることを示します。番号が書かれていればその文字番号で示される文字が回避文字となります。
たとえば、
SHUNCHAR CONTROLS 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 127
と指定されている場合、制御文字とされているもの、及び 0 〜31番と 127番の文字が回避文字となります。
ここでまた BASESET と DESCSET が出てきますが、ここでは「構文参照文字集合」というものを規定しています。マーク付けに使う区切り子などは、この「構文参照文字集合」に含まれるものでなければなりません。たいていは
BASESET "ISO 646IRV:1991//CHARSET
International Reference Version
(IRV)//ESC 2/8 4/2"
DESCSET 0 128 0
として、いわゆる ASCII 文字を使えるようにしてあります。
特殊な機能を割り当てる文字を指定します。
RE(レコード終了)、RS(レコード開始)、SPACE(空白)の三つは必須です。それぞれの機能に文字を一つずつ割り当て、文字番号を指定します。
それに加え、特定の文字に追加機能を割り当てることができます。割り当てられる追加機能は FUNCHAR(休止機能文字), MSICHAR,(マーク認知開始文字), MSOCHAR(マーク認知終了文字), MSSCHAR(マーク認知抑制文字), SEPCHAR(分離子文字) の五種類です。
たとえば、HTML4.0 では
RE 13
RS 10
SPACE 32
TAB SEPCHAR 9
となっていて、レコード終了に13番の文字(CR)、レコード開始に10番の文字(LF)、空白に32番の文字(ASCII SPACE)が割り当てられています。さらに追加機能として、TAB と言う名の分離子文字として 9番の文字(TAB)が割り当てられています。
分離子文字と言われても分かりにくいかも知れませんが、要するに ASCII SPACE と同じ扱いです。なお、HTML4 では PRE の中で TAB を使うことは避けるようにというお達しがありますし、ISO/IEC 15445 では TAB は ASCII SPACE に置き換えられることになっています。
名前文字、名前字句として使える文字の指定を行い、大文字小文字の同一視を行うか否かを規定します。
LCNMSTRT, UCNMSTRT は名前開始文字として追加する文字を指定します。無指定であれば英大文字と小文字のみが使えます。
LCNMCHAR, UCNMCHAR は名前文字として追加する文字を指定します。無指定であれば、英大文字小文字と数字が使えます。
NAMECASE は 名前字句の大文字小文字を同一視するか否かを規定します。GENERAL で名前字句全般の大文字小文字の区別、ENTITY で実体名の大文字小文字の区別について規定します。YES と指定されている場合、英小文字はすべて英大文字に変換され、LCNMSTRT は対応する UCNMSTRT に、LCNMCHAR は対応する UCNMCHAR に置き換えられます。
たとえば HTML4.0 では、
NAMING LCNMSTRT ""
UCNMSTRT ""
LCNMCHAR ".-_:"
UCNMCHAR ".-_:"
NAMECASE GENERAL YES
ENTITY NO
となっていますから、名前開始文字は英大文字と小文字のみ、名前文字には英大文字小文字と数字に加えて .-_: の文字を使うことができ、名前字句の大文字小文字は同一視され、実体名の大文字小文字は区別されます。
ここの指定は普通はいじりませんが、何らかの事情で区切り子の機能を別の文字に割り当てたいときに指定を行ったりできます。たとえば STAGO(開始タグ開始区切り子) は普通 < という文字ですが、これを ; とか : とか別の文字列に変えることができます。
GENERAL は一般区切り子について定めます。次いで SGMLREF と書かれますが、これは規格参照の意で、このキーワードは必須です。
普通はこれだけで終わるのですが、区切り子の機能を別の文字に割り当てたいときにはこの後に指定を行います。たとえば、
SYNTAX DELIM GENERAL SGMLREF PIC "?>" NET "/>"
と宣言されている場合、処理命令終了区切り子には ">" の代わりに "?>" を、NET 区切り子には "/" の代わりに "/>" を使うことになります。その他については規格参照です。
ここではまだ > などの実体が定義されていないことに注意してください。よって文字実体参照は使えません。数値文字参照は使えます。
SHORTREF は短縮参照区切り子について定めます。説明は省略。
実は短縮参照についてはあまり良く分かってないので。
DELIM は区切り子を改造しましたが、NAMES は予約名を改造します。たとえば #IMPLIED というキーワードを別のもので代替したりできます。
NAMES の後ろには例によって SGMLREF と書かれます。これは必須です。名前を変えたい予約名があればその後に指定します……が、この機能が使われることはほとんどありません。予約名を変えても、DTD を読む者に余計な混乱を与えるだけでしょう。
当然ですが、SGML宣言中の予約名を変えることはできません。
さまざまな量の値を定めます。
QUANTITY に次いで SGMLREF と書かれます。これは必須です。
その後、必要に応じて以下のような値を定めます。
ATTCNT …… 要素の属性定義の中の名前・名前字句。SGML規格の定める既定値は 40。
ATTSPLEN …… 開始タグの属性指定の正規の長さ。既定値は 960。
BSEQLEN …… 短縮参照列の中の空白列の長さ。既定値は 960。
DTAGLEN …… データタグの長さ。既定値は 16。
DTEMPLEN …… データタグ形式・データタグひな形の長さ。既定値は 16。
ENTLVL …… 実体の入れ子の深さ(一番外のものは数えない)。既定値は 16。
GRPCNT …… 群の中の字句の個数。既定値は 32。
GRPGTCNT …… モデル群の中の字句の総個数。既定値は 96。
GRPLVL …… モデル群の入れ子の深さ(一番外のものも数える)。既定値は 16。
LITLEN …… 表記の長さ。既定値は 240。
NAMELEN …… 名前・名前字句・数などの長さ。既定値は 8。
NORMSEP …… 正規の長さの計算の際に分離子を数えるのに使う。既定値は 2。
PILEN …… 処理命令の長さ。既定値は 240。
TAGLEN …… 開始タグの長さ。既定値は 960。
TAGLVL …… 開いている要素の入れ子の深さ。既定値は 24。
なお、DTEMPLEN, LITLEN, PILEN, TAGLEN は区切り子を除いた長さです。たとえば、<GI attrib="……"> などという開始タグは、< や > を除いた中身の長さが TAGLEN の値以下であれば良いことになります。
特に重要なのは NAMELEN です。これは名前字句の長さを規定するのですが、要素の名前、実体の名前、id 属性、引用符で括られていない属性値、等々、極めて多くのものがこの値の制限を受けます。既定値ではこの値がわずかに 8 しかありませんので、このままでは BLOCKQUOTE 要素の宣言さえままなりません。
あとは LITLEN, TAGLEN あたりがそれなりに重要です。前者は引用符で括られたリテラル値の長さを、後者は開始タグの長さを規定します。これを越えてしまうようなマーク付けはできないので注意が必要です。
"FEATURES" で始まる部分です。
マーク付けの最小化を使用するか否かを規定する部分です。省略タグ、短縮タグの使用可否もここで決まります。
DATATAG でデータタグの使用可否を規定します。データタグとは、データ内の文字列をタグに置換する機能で、たとえばコンマ区切りのデータがあったとき、そのコンマをタグに置き換えたりすることができます。この機能を使用するなら DATATAG YES, 使用しないなら DATATAG NO と宣言します。
OMITTAG は省略タグ機構の使用可否を決めます。詳しくはSGMLの省略タグ機構を参照してください。使用する場合は OMITTAG YES, 使用しない場合は OMITTAG NO です。
RANK は「付番」の使用について規定します。付番というのは、大雑把に言うと要素名に添え字をつける機能です。使用する場合は RANK YES, しない場合は RANK NO です。
SHORTTAG は短縮タグ機構について規定します。詳しくは SGMLの短縮タグ機構を参照してください。この機能を使う場合は SHORTTAG YES, 使わない場合は SHORTTAG NO です。
SIMPLE(単純連結), IMPLICIT(暗黙連結), EXPLICIT(明示連結)のそれぞれについて YES/NO で使用可否を規定します。と言われても何が何だか分からないかも知れませんが、実は私にも良く分かっていません。以上(笑)。
CONCUR, SUBDOC, FORMAL のそれぞれについて YES/NO で宣言します。
以上(笑)。
"APPINFO" で始まる部分で、アプリケーションに特有の情報が記述されます。"NONE" と書かれていれば特に情報はありません。たいてい "NONE" です。
SGML宣言の中には頻繁に "SGMLREF" というキーワードが現れます。これは、その値が SGML規格で定められた既定値を参照するものであることを示します。
こんなものを書かなくても、宣言の省略時には SGML規格の既定値が参照されることは自明なのですが、SGML宣言を読む人間に対して「宣言されていない値は規格に従うんだよ」と注意を促す役割を持つのだそうです。
というわけで、多くの場所でこのキーワードは必須となっています。