1. Valid XML の仕組み

目次

1.1. Web SGML 適応

XMLSGML のサブセットであることを旨として設計されていますが、一部旧来の SGML と互換性のない部分があります。そこで ISO は、XML を SGML の完全なサブセットとするために、XML の仕様を変更するのではなく SGML の仕様の方を改正してしまうという逆転の発想を用いました。この新しい SGML 仕様として策定されたのが SGML TC2 Annex K (Web SGML 適応) です。

XML が SGML でどのように定義されているかを理解するためには、旧来の SGML の知識だけではなく、この Web SGML についての知識が必要になります。以下では、旧来の SGML ついての簡単な知識があることを前提に、Web SGML と妥当な XML の SGML 宣言の定義について解説します。

なお、旧来の SGML の文法についてはマニアックな文法論議などが詳しいと思いますので、適宜そちらを参照して下さい。

SGML Annex K 準拠の文書であることを示すためには、SGML 宣言の最小リテラルを "ISO 8879:1986 (WWW)" と記述します。WWW は文字通り Web SGML であることを示すものです。なお、Annex K は Annex J Extended Naming Rules (拡張命名規則、最小リテラル "ISO 8879:1986 (ENR)" )を包含するものなので、拡張命名規則の構文を使用できます。

1.2. 新しい区切り子

Web SGML では、十六進数文字参照という新しい参照の定義と、NET (簡略終了タグ) の定義変更に伴い、いくつかの新しい区切り子が導入されています。

1.2.1. 十六進数文字参照

十六進数文字参照HTML 4.01 でも使用可能ですが(*1)、Web SGML で導入された新しい文字参照です(旧来の UA が十六進数文字参照に対応していないのはこのためです)。

この文字参照の導入により、文字参照の構文は次のように変更されました。

文字参照 = 名前指定文字参照 | 数値指定文字参照 | 十六進数文字参照

十六進数文字参照 = hcro, 十六進数+, 参照終了

十六進数 = [0-9a-fA-F]

hcro (十六進数文字参照開き) は新しく導入された区切り子であり、デフォルトでは定義されません。このため、十六進数文字参照を使用するには、SGML 宣言の DELIM 項目で HCRO を明示的に定義する必要があります。XML や HTML 4.01 では HCRO "&#x" となっており、十六進数文字参照は &#x で開始することになります。

なお、XML は NAMECASE GENERAL NO ですから、区切り子の大文字小文字についても区別があり、HCRO を &#X として記述することはできません。一方、HTML 4.01 は NAMECASE GENERAL YES であるため、区切り子の大文字小文字についても区別がなく、十六進数文字参照を 文 と記述することもできます。ちなみに十六進数そのものは 十六進数 = [0-9a-fA-F] と定義されているので、XML の場合にも 書 書 どちらで記述しても構いません。

hcro の認知様相は、他の文字参照同様 CON LIT となっています。また、hcro は制約 HEX (直後に十六進数が続くこと) を持ちます。

*1: HTML 4 と十六進数文字参照

なお、HTML 4.0 は従来の SGML ("ISO 8879:1986") で定義されているにも関わらず、十六進数文字参照の使用が認められていました(これは当時 Web SGML が策定中であったためです)。このため、実は HTML 4.0 の仕様には SGML に適合していない部分があったのです。この不整合は、HTML 4.01 において、定義言語を Web SGML ("ISO 8879:1986 (WWW)") とすることで修正されています。

1.2.2. NET (簡略終了タグ)

旧来の SGML では、NET 可能開始タグは次のように定義されていました。

NET 可能開始タグ = stago, 共通識別子指定, 属性指定並び, s*, net

Web SGML では、この構文が次のように変更されています。

NET 可能開始タグ = stago, 共通識別子指定, 属性指定並び, s*, nestc

nestc (NET 可能開始タグ閉じ) は、文字通り NET 可能開始タグのタグ閉じとなる新しい区切り子です。デフォルトでは net と同じ文字列が割り当てられることになっているため、特に区切り子の指定をしない限り、NET を用いた要素の構文は旧来のものと変わりません。

なお、nestc の認知様相は TAG であり、併せて net の認知様相は CON に変更されています (nestc は制約なし、net の制約は旧来通り ELEM)。それぞれの機能に併せ、旧来の net から認知様相と制約が分割されたと見なしてよいでしょう。

XML での定義はそれぞれ NESTC "/" NET ">" となっているので、例えば <br></br><br/> と記述することができます。ただし、NET の記述規則は後述する SGML 宣言の SHORTTAG STARTTAG NETENABL 項目で細かく定義されており、XML では <p>…段落…</p> という記述を <p/…段落…> と最小化することはできません。

1.3. 空要素終了規則

旧来の SGML と XML との大きな相違の一つとして、XML では強制空要素の終了タグの省略が禁じられているということが挙げられます。

旧来の SGML では、強制空要素の終了タグは他の要素の終了タグとは異なる制約を持ち、いかなる場合も記述してはならない(常に省略しなければならない)ことになっていました(*2)。これに対し、Web SGML では SGML 宣言に EMPTYNRM (NRMnormal の略?) という新しい項目が導入され、強制空要素の終了タグを通常の要素の終了タグと同様に扱えるよう設定することができるようになりました。

EMPTYNRM の宣言値は YES または NO となります。ここで EMPTYNRM YES が宣言された場合、強制空要素の終了タグに関する特殊な制約は全てなくなり、扱いは通常の要素の終了タグと同様になります(なお、強制空要素の開始タグと終了タグの間には、空白文字を含め一切の文字が許されません)。XMLでは EMPTYNRM YES かつ OMITTAG NO が宣言されているため、強制空要素の終了タグも必ず記述しなければならないことになるわけです。

一方、EMPTYNRM NO が宣言された場合には、空要素の終了タグは旧来の SGML と同じ制約を受けることになります (EMPTYNRM が省略された場合にも、暗黙に EMPTYNRM NO が宣言されたものと見なされます)。

なお、構文上 EMPTYNRM 項目は後述する IMPLYDEF 項目と組で記述することになっているため、一方を記述する場合には必ず他方も記述しなければなりません。また、Web SGML の仕様書には、備考として省略可能な項目/パラメタも全て指定することが望ましいという記述があります。

*2: 強制空要素の終了タグ

旧来の規則では、例えば OMITTAG NO の場合や、要素型宣言が <!ELEMENT foo - - EMPTY > などと記述された場合にも、強制空要素の終了タグは省略することになっていました。

Another HTML-lint : Notice によると、IE 3.0 のβ版 DTD には <!ELEMENT NOEMBED - - EMPTY> という記述があったそうですが、この場合にも noembed の終了タグは記述できません。終了タグを省略すれば妥当な記述と見なされますが、タグ省略最小化の指定につられて終了タグを記述してしまうと、逆にエラーとなってしまいます。

実は EMPTYNRM NO の場合、強制空要素の要素型宣言でのタグ省略指定は全く意味を持ちません。強制空要素が一般に <!ELEMENT foo - O EMPTY > として宣言されるのは、単に備忘のためにそう指定するのが望ましいとされていることによるものです。

1.4. 短縮タグ機構

SGML には、タグを短縮するためのいくつかの機構が用意されています。旧来、SGML 宣言の SHORTTAG (短縮タグ機構) 項目の宣言値は YES または NO の二者択一だったため、これらの短縮機構は「全て利用できる」か「全て利用できない」の両極端から選択しなければなりませんでした。

これに対し Web SGML では、これらの短縮機構のそれぞれについて「利用する」「利用しない」を設定できるようになっています(旧来通りに一括して YES/NO で設定することもできます)。具体的には SHORTTAG 項目に、STARTTAG オプション、ENDTAG オプション、ATTRIB オプションの三つのオプションを設定できるようになりました。XML の SGML 宣言では、SHORTTAG 項目は次のように宣言されています。

SHORTTAG
    STARTTAG
        EMPTY    NO
        UNCLOSED NO
        NETENABL IMMEDNET
    ENDTAG
        EMPTY    NO
        UNCLOSED NO
    ATTRIB
        DEFAULT  YES
        OMITNAME NO
        VALUE    NO

1.4.1. STARTTAG オプション

STARTTAG オプションは、文字通り開始タグの短縮について定めるものです。EMPTY 項目UNCLOSED 項目は、それぞれ空の開始タグと閉じない開始タグの使用の可否を YES/NO で設定します。XML ではどちらも NO です。

NETENABL 項目は、NET の使用の可否について NO/ALL/IMMEDNET で設定します。NETENABL NONETENABL ALL は、それぞれ旧来の SHORTTAG NOSHORTTAG YES の場合の NET の扱いに相当します。

NETENABL IMMEDNET は、「内容を持たない要素に対し」「NET 可能開始タグ及び NET を同時に記述」することのみを可能にします。要素の内容が空でない場合や、NET を記述しない場合には NET 可能開始タグを記述することはできません。XML では NETENABL IMMEDNET が宣言されているため、前述の通り <p/…段落…> という短縮はできないことになるわけです。

なお、NET 可能開始タグを記述せずに NET を記述することができないのは、旧来の SGML と同様です。また EMPTYNRM YES が宣言されていない場合、強制空要素には終了タグを記述できませんから、当然これに NET を記述することもできません。

ちなみに、内容を持たない要素というのは、強制空要素だけでなく、たまたま内容を持たない要素 ― 例えば表の中の空のセル<td></td>など ― を含みます。従って、例えば XHTML 1.1 の場合には、次のような記述が行えることになるわけです。

<p>一行目<br/>
二行目</p>

<table>
 <tr><th/><th>列見出し1</th><th>列見出し2</th></tr>
 <tr><th>行見出し1</th><td>項目1-1</td><td>項目1-2</td></tr>
 <tr><th>行見出し2</th><td>項目2-1</td><td>項目2-2</td></tr>
</table>

ここで <br/> 及び <th/> の完全形式は、それぞれ <br></br> <th></th> となります。

1.4.2. ENDTAG オプション

ENDTAG オプションは、STARTTAG オプション同様、終了タグの短縮について定めるものです。EMPTY 項目は空の終了タグの使用の可否について、UNCLOSED 項目は閉じない終了タグの使用の可否について、それぞれ YES/NO で設定します。XML ではどちらも NOです。

STARTTAG オプションの記述と併せて、XML では空タグ及び閉じないタグは一切使用できないことになります。

1.4.3.ATTRIB オプション

ATTRIB オプションは属性の短縮と省略について定めます。

DEFAULT 項目は、省略時値を利用した属性の省略の可否を YES/NO で設定します。XML は DEFAULT YES であるため、必須属性 (#REQUIRED) 以外の属性は、省略されても省略時値を与えられたものとしてパーザに補われます。旧来の SGML では、SHORTTAG YES / SHORTTAG NO のどちらが宣言されていても省略時値を利用した属性の省略を行うことができましたが、これを禁止するよう設定することもできるようになったわけです。なお、DEFAULT NO であっても属性リスト宣言に (#REQUIRED 以外の) 省略時値を設定することもできますが、省略された属性は補われないことになります。

OMITNAME 項目は、一意な名前からなる値を与えられた属性の、属性名及び vi(値標識) = の省略の可否について、YES/NO で設定します。なお、OMITNAME YES で属性名と vi を省略する場合には、属性値指定を属性値リテラルとしてでなく属性値として記述する必要があります。XML は OMITNAME NO ですから、属性名の省略はできません。

VALUE 項目は、属性値が名前からなる場合に、属性値指定を属性値リテラルとしてでなく属性値として記述することの可否について、YES/NO で定めます。XML は VALUE NO ですから、属性値指定を属性値として記述することはできず、常に属性値リテラルとして記述する必要があります。

1.5. 空でもよい属性定義リスト

旧来の SGML での属性リスト宣言は、次のように定義されていました。

属性リスト宣言 = mdo, "ATTLIST", ps+, (結合要素型 | 結合記法名),
                ps+, 属性定義リスト, ps*, mdc

属性定義リスト = 属性定義, (ps+, 属性定義)*

Web SGML では、これが次のように変更されています(属性リスト宣言の構文変更については、直接 XML に関係がないので割愛します)。

属性定義リスト = (属性定義, (ps+, 属性定義)*)?

つまり、旧来の属性リスト宣言では最低一つ以上の属性定義がなされる必要があったのですが、これが空でもよいことになりました。XML もこの構文を採用しており、次のような宣言は妥当と見なされます。

<!ATTLIST foo >

なお、このような記述が認められるようになった理由は、恐らく <!ENTITY % foo.attrib "" > の時にも <!ATTLIST foo %foo.attrib; > という宣言が妥当となるようにするためであると思います。実際、XHTML のモジュールを利用する場合など、この記述を行えないと不便であることは多々あります。

旧来の SGML では、foo 要素型の属性リストが空であるかも知れない場合には、例えば属性リスト宣言全体を条件付き区間で囲み、状態キーワードとなるパラメタ実体を新たに定義する必要があったのですが、そのような面倒をしなくとも済むようになったわけです。

1.6. 内容中の空白

旧来の SGML には次のような規則がありました。

内容の中に現れる RS は、マークと解釈できない場合、無視する。

内容の中で、すべての参照の置換及びマークの認知の後に残る RE は、次の(1)〜(3) のとおりにそれがマークのためだけに存在するのでなければ、データとして扱う。

このため、例えば HTML 4.01 では、次のような記述は等価に扱われます。

Web SGML では、SGML 宣言に OTHER KEEPRSRE という項目が設けられ、オプションでこの規則を適用せず、要素内容中の全ての空白文字を保持することができるようになりました。

RS 及び RE を保持する場合は KEEPRSRE YES 、保持しない場合は KEEPRSRE NO を宣言します。XML は KEEPRSRE YES ですので、2.10 White Space Handling にある通り、パージングの段階では全ての空白文字が保持されることになります。

1.7. 容量集合と量集合

Web SGML では、SGML 宣言の容量集合・量集合それぞれの項目において、新たに NONE という宣言値を取ることができるようになりました。CAPACITY NONESYNTAX QUANTITY NONE は、どの容量も指定されていないことを示します。

XML ではどちらも NONE が宣言されているため、容量に関する構文的な制約は存在しません。

この文書のステータス

URI
http://www.satoshii.org/markup/websgml/valid-xml
初版
2002-02-05
最終更新
2005-09-15
著者
石川哲志
Copyright © 2002-2003, 2005 Satoshi ISHIKAWA, All Rights Reserved.