前章では Web SGML 適応で新たに追加・変更された定義のうち、妥当な XML の定義を理解するために必要なものについて解説しました。しかし、いわゆる整形式 XML 全般の定義を理解するためには、もう少し必要となる知識があります。以下では妥当な XML と整形式 XML の差違についても触れながら、整形式 XML の定義について解説していきます。
なお、妥当/整形式という区別は作者によってなされるものではありません。この区別は、文書の利用者が妥当性検証を行う SGML 宣言を用いるか否かによって決定されるものです。パーザに妥当性検証用の SGML 宣言が与えられれば、文書は妥当な XML として扱われますし、単に整形式性を検証するだけの SGML 宣言が与えられれば、文書は整形式 XML として扱われるのです。
まずここで、改めて「妥当」「整形式」という語の定義について確認していきます。
妥当な XML 文書とは、整形式 XML 文書のうち特に型妥当であり完全宣言済みであるものを言います。
型妥当であるとは、文書インスタンスが文書型宣言の定義 ― 例えば要素の内容モデルや属性の宣言値 ― に完全に適合しているということです。詳しくは後述しますが、この文書型宣言の定義
というのは暗黙のデフォルト宣言を含みます。
また完全宣言済みであるとは、文書インスタンスに現れる全ての要素や属性が DTD で明示的に宣言されていることを言います。これは、記述された要素や属性が宣言されてさえいればよく、内容モデルや宣言値に則った記述が行われているかどうかは関係しません。
そして整形式 XML 文書とは、文書インスタンスが完全タグ付きであり、かつ完結記憶である適合 SGML 文書を言います。
完全タグ付きとは、全ての要素に終了タグと空でない開始タグが記述されており、全ての属性指定に属性名が記述されていることを言います。これは DATATAG NO
、RANK NO
、OMITTAG NO
、SHORTTAG STARTTAG EMPTY NO
、SHORTTAG ATTRIB OMITNAME NO
、EMPTYNRM YES
を満たすということと等価です。
また完結記憶であるとは、全ての要素(及びマーク区間)がそれの開始したのと同じ実体の中で終了することを言います。例えば、次の文書は完結記憶ではありません。
<!DOCTYPE doc [
<!ELEMENT doc (para)+ >
<!ELEMENT para (#PCDATA) >
<!ENTITY STAG-para "<para>" >
<!ENTITY ETAG-para "</para>" >
]>
<doc>
&STAG-para;…文章…&ETAG-para;
</doc>
この例では、para 要素は実体 "STAG-para" で始まり、実体 "ETAG-para" で終了してしまっているわけです。旧来の SGML ではこのような構文が許されていますが、XML には整形式でなければならない(完結記憶でなければならない)という制約がありますから、上のような記述は不可ということになります。
整形式という概念を学ぶ上で最も注意が必要なのは、整形式 XML は型妥当でなくとも良いという点です。これは言い方を換えれば「型妥当でない文書も正しい XML 文書と見なされる」ということを意味します。
ここで、改めて整形式 XML というものを三種類に大別してみます。
型妥当かつ完全宣言済みである
XML 文書とは取りも直さず妥当な XML 文書のことですが、妥当でない整形式 XML についても型妥当であるか否かの区別があることは覚えておいて下さい。
# なお、妥当でないのに型妥当であるような状態が有り得るのか、ということに関しては、後で詳しく述べます。それがこの "整形式 XML の仕組み" の趣旨です。
さて、前節で触れた型妥当でない整形式 XML 文書
とは、例えば次のようなものです。
<?xml version="1.0" >
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" >
<body>
<p><div>bar</div></p>
</body>
この例では、文書型宣言の示す文書要素型と実際の文書要素が食い違っています。また、p の子要素として div 要素が記述されていますが、これは p の要素型宣言で禁止されています。上の文書はこれらの点で型妥当になっていないのですが、それでもなお整形式であるために、XML として認められてしまうわけです。
このような記述は旧来の SGML では当然認められません。しかし Web SGML はこのような文書も適合 SGML として認めてしまうようなオプションを持っています。それが、SGML 宣言の OTHER VALIDITY 項目と OTHER ENTITIES 項目です。
OTHER VALIDITY 項目は、文書インスタンスの妥当性についての表明を行うか否かを NOASSERT/TYPE で設定します。
表明とは、換言すれば「この文書のインスタンスは型妥当である」といった「宣言」のことです。妥当性の検証というのは、このあらかじめなされる「表明」に応じて行われます。SGML 宣言において「文書インスタンスは型妥当になっている」という表明がなされていれば、パーザは型妥当でない部分があった場合に「SGML 宣言での表明に反する箇所がある」というエラーを報告することができるわけです。
逆に言うと「この文章の型妥当性は保証しない」という表明がなされている場合、パーザは型妥当になっていない箇所を発見しても「表明通り」と見なしますから、エラーにはなりません。VALIDITY TYPE
は「文書インスタンスは型妥当である」ということを表明します。一方、VALIDITY NOASSERT
は「特に表明は行わない (= 型妥当性について保証しない)」ということを意味します。
XML パーザは 妥当性についての検証を行わなくともよい
ことになっていますから、単なる整形式 XML として解析を行う場合は VALIDITY NOASSERT
が宣言されます。ただし、妥当性検証を行う場合には VALIDITY TYPE
が宣言されることになるわけです。
なお、1997年12月04日付けの Approved text (ISO/IEC JTC1/WG4 N1955) の段階では OTHER VALIDITY TAG
(文書インスタンスは完全タグ付き) / OTHER VALIDITY TYPE-TAG
(文書インスタンスは完全タグ付きかつ型妥当)といった宣言値も考えられていましたが、1998年05月15日付けの Approved Text (同N1981) 以降は NOASSERT/TYPE のみということになりました。
1997年12月15日に W3C が NOTE として公開した Comparison of SGML and XML は、N1955 に則ったものです。このため、整形式 XML の SGML 宣言として OTHER VALIDITY TAG
を宣言していますが、この宣言は最終的な規格には適合しません。またこの段階では XML 1.0 (1998年2月10日) も勧告されておらず、勧告候補(1997年12月08日)の段階でした (N1955 の執筆時点では1997年11月17日の草案段階?)。このため、Comparison of SGML and XML の記述には若干 XML 勧告との食い違いもあることに注意して下さい。
# ちなみに、OTHER VALIDITY 項目ではあくまで型妥当であるか否かということを表明するのみで、その他の文法の適合性とは全く関係がありません。例えば OTHER VALIDITY NOASSERT
であっても、タグの不正な短縮などがあればそれはエラーとなります。
# OTHER VALIDITY TAG
という宣言値がなくなったのは、完全タグ付きであることはその他の SGML 宣言(完全タグ付きの項参照)によって表現可能であるからだと思います。
OTHER ENTITIES 項目は、一般実体参照に関する妥当性について表明します。表明を行わない場合は ENTITIES NOASSERT
を宣言し、何らかの表明を行う場合には次のような宣言を記述します。以下に XML の SGML 宣言の例を挙げておきます。
ENTITIES
REF ANY
INTEGRAL YES
REF ANY
は文書が制約のない実体参照を持つという表明です。外部参照を持たないことを表明するには REF INTERNAL
を、参照を持たないことを表明するには REF NONE
を、それぞれ宣言します。
INTEGRAL YES
は文書インスタンスが完結記憶であるという表明です。XML は整形式(=完結記憶)ですから INTEGRAL YES
であり、前述の通り例1のような記述は行えません。完結記憶でないことを表明するには INTEGRAL NO
を宣言します。
旧来の SGML で実体参照を記述するためには、あらかじめ DTD 中で実体を宣言しておく必要がありました。これに対し、Web SGML では SGML 宣言の SYNTAX 項目に ENTITIES(定義済みデータ文字実体)という項目が導入されており、SGML 宣言中で数値文字参照を実体とする一般実体を定義することができるようになっています。
具体的な記述例として、XML の SGML 宣言での定義を示しておきます。
ENTITIES
"amp" 38
"lt" 60
"gt" 62
"quot" 34
"apos" 39
"ENTITIES" という文字列に続き、実体名を示すパラメタリテラルと、その実体となる数値文字参照の文字番号を順に記述していきます。ちなみに、定義済みデータ文字実体が必要ない場合には ENTITIES NONE
として宣言しておきます。旧来通り ENTITIES 項目を省略した場合にも、ENTITIES NONE
を宣言したものとして扱われます。
上の定義の場合は、DTD の内部サブセットの先頭で次の宣言をするのと同じ意味になります (ENTITIES "amp" 38
という定義の場合、"&"の置換テキストは"&"ではなく"&"となることに注意して下さい)。
<!ENTITY amp "&#38;" >
<!ENTITY lt "&#60;" >
<!ENTITY gt "&#62;" >
<!ENTITY quot "&#34;" >
<!ENTITY apos "&#39;" >
XML で、これら五つの実体参照が実体宣言なしでも記述できるのは、この機構によるものです。
なお、上の定義は Valid XML・Well-Formed XML 共通のものです。従って、妥当な XML でも "&" や "<" といった実体参照は宣言せずに記述できることになります。ただし、XML 勧告には相互運用性のためには、妥当な XML 文書ではこれらの実体も他の実体同様に宣言すべきである
という記述があり、XHTML 1.1 などでもこれらの実体は旧来通りに宣言されています。
文書型宣言の記述されていない整形式 XML 文書は、屡々「DTD が存在しない」XML であると解説されます。しかし、SGML 的にはこのような文書にもきちんと DTD (と文書型宣言)が存在しますし、実は文書型宣言のない整形式 XML 文書は常に型妥当にもなっています。
この「文書型宣言がないにも関わらず型妥当である」という状態を可能にしているのが、Web SGML で導入された暗黙のデフォルト宣言という機構です。
暗黙のデフォルト宣言に関する定義は、SGML 宣言の MINIMIZE IMPLYDEF 項目で行います。IMPLYDEF 項目には ELEMENT、ATTLIST、DOCTYPE、ENTITY、NOTATION の五つのパラメタがあります。
ELEMENT パラメタは、要素型を暗黙に宣言することの可否について YES/NO/ANYOTHER で宣言します。ここで ELEMENT YES
は、DTD 中で明示的に宣言されなかった要素型が - O ANY
と暗黙に宣言されることを意味します。
妥当性を検証しない場合、XML の SGML 宣言は ELEMENT YES
であり、宣言されていない要素型は暗黙に宣言されたものと見なして処理を行います。
<?xml version="1.0" ?>
<!DOCTYPE doc []>
<doc>
<title>題名</title>
<para>…段落…</para>
</doc>
例えば上の整形式 XML 文書は、次の文書型宣言がなされたものと見なされます(SGML では OMITTAG NO
であってもタグ省略最小化を記述できます)。
<!DOCTYPE doc [
<!ELEMENT doc - O ANY >
<!ELEMENT title - O ANY >
<!ELEMENT para - O ANY >
]>
ELEMENT ANYOTHER
も同様に、宣言されなかった要素型が - O ANY
と宣言されることを意味します。ただし、この場合には当該要素型が直接再帰要素(*1)となることは禁止されます。
ELEMENT NO
の場合には、旧来通り明示的に宣言されていない要素の出現はエラーとなります。これは、文書インスタンスが完全宣言済みであるということの必要条件です。妥当であるとは型妥当かつ完全宣言済み
であるということですから、妥当性を検証する場合には ELEMENT NO
を宣言するということになります。
ちなみに、型妥当であるとは文書インスタンスが文書型宣言の記述に完全に適合しているということです
と述べましたが、実はこれは「文書型宣言の記述に全く反していない」と表現する方が正確です。
型妥当性の制約では、宣言が暗黙のものであるか否かは問われません。暗黙の宣言に対して型妥当でないような記述は有り得ませんから、型妥当か否かが分かれるのは明示的に宣言された箇所に限られることになります。上に例示した整形式 XML 文書も、これで型妥当になっているのです。
なお、IMPLYDEF 項目が省略された場合には全てのパラメタに NO
が指定されたものと見なされ、旧来通り暗黙の宣言は行われません。
同じ型の要素を子要素とする要素を直接再帰要素と言います。
<!DOCTYPE doc >
<doc>
<span>span 要素1
<span>span 要素2
</doc>
上の例文は、ELEMENT YES
かつ OMITTAG YES
の場合には、次のように見なされます(実際の内容モデルは ANY
ですが、その他の定義を併せて考えれば以下の宣言と同じ意味になります)。
<!DOCTYPE doc [
<!ELEMENT doc - O ( #PCDATA | doc | span )* >
<!ELEMENT span - O ( #PCDATA | doc | span )* >
]>
<doc>
<span>span 要素1
<span>span 要素2</span></span>
</doc>
ELEMENT ANYOTHER
かつ OMITTAG YES
の場合には次のようになります。
<!DOCTYPE doc [
<!ELEMENT doc - O ( #PCDATA | span )* >
<!ELEMENT span - O ( #PCDATA | doc )* >
]>
<doc>
<span>span 要素1</span>
<span>span 要素2</span>
</doc>
ATTLIST パラメタは、ELEMENT パラメタと同様に、宣言されなかった属性を暗黙的に宣言することについて YES/NO で設定します。
ATTLIST YES
の場合、明示的に宣言されなかった属性は CDATA #IMPLIED
と宣言されます。ATTLIST NO
の場合は、このような宣言は行われません。ELEMENT パラメタと同様、妥当性を検証しないパーザは ATTLIST YES
、妥当性を検証する場合は(完全宣言済みであるという表明として) ATTLIST NO
です。
<?xml version="1.0" ?>
<!DOCTYPE html []>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
<head>
<title>題名</title>
</head>
<body>
<p>…段落…<p>
</body>
</html>
ELEMENT パラメタと併せ、上の整形式 XML 文書では次の文書型宣言がなされたものと見なされます。
<!DOCTYPE html [
<!ELEMENT html - O ANY >
<!ATTLIST html
xmlns CDATA #IMPLIED
xml:lang CDATA #IMPLIED
>
<!ELEMENT head - O ANY >
<!ELEMENT title - O ANY >
<!ELEMENT body - O ANY >
<!ELEMENT p - O ANY >
]>
DOCTYPE パラメタは、暗黙の文書型宣言が外部サブセットに宣言を持つことの可否について、YES/NO で設定します。詳しくは後述の省略された前書きを参照して下さい。
ENTITY パラメタは、宣言されなかった一般実体を暗黙に宣言することの可否について YES/NO で設定します。ENTITY YES
の場合、宣言されなかった一般実体は SYSTEM
と宣言されます。
XML では、Validity constraint: Entity Declared
とある通り、妥当な XML 文書では ENTITY NO
が宣言されていることになります。一方、Well-formedness constraint: Entity Declared
には、次のような注記があります。
Note that if entities are declared in the external subset or in external parameter entities, a non-validating processor is not obligated
to read and process their declarations; for such documents, the
rule that an entity must be declared is a well-formedness constraint only
if standalone='yes'
.
これは、「外部宣言集合を持つ文書(あるいは任意の文書?)では、standalone="yes"
が宣言されていない限り、あらゆる一般実体参照が前述の整形式制約を満たす」ということを意味するものと思われます(そう解釈せざるを得ない)。すなわち、次のような文書は整形式になります。
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" >
<html> ... &hoge; ... </html>
勿論 XHTML 1.1 では hoge という実体は宣言されていないわけですが、non-validating processor からすれば「もしかすると自分の読んでいない外部 DTD で宣言されているのかも知れない」ということになりますから、整形式と見なさざるを得ないわけです。
SGML 的には、実体は必ず宣言されていなければなりませんから、この場合、non-validating processor が hoge という実体を暗黙に宣言したものと解釈することになります。結局、XML では、ENTITY パラメタは次のように宣言されているものと考えられます。
standalone="yes" | standalone="no" (外部宣言集合なし) | standalone="no" (外部宣言集合あり) | |
---|---|---|---|
validating processor | ENTITY NO | ENTITY NO | ENTITY NO |
non-validating processor | ENTITY NO | ENTITY NO (ENTITY YES ?) | ENTITY YES |
ただし、SGML Annex L.2 SGML Declaration for XML では、non-validating processor に対する SGML 宣言として ENTITY NO
を宣言しています。単に、外部宣言集合を持つような文書を non-validating processor で扱うことを考慮していなかっただけかも知れませんが、詳細は不明です。ちなみに Comparison of SGML and XML や N1955 では ENTITY YES
が宣言されています。
# いずれにせよ、XML 1.0 もしくは SGML Annex L のどちらかの記述(ないし、その記述に対する筆者の解釈)に不備があるように思います。
同様に、NOTATION パラメタは宣言されなかった記法を暗黙的に宣言することについて YES/NO で設定します。NOTATION YES
の場合、宣言されなかった記法は SYSTEM
と宣言されます。
XML では、Notation Declared
は妥当性制約として記述されているのみで、整形式制約にはなっていません。従って、validating processor では NOTATION NO
ですが、non-validating processor では NOTATION YES
です。
# ちなみに、整形式 XML の妥当性を検証するか否かという点で SGML 宣言に差違があるのは、ここまで述べた OTHER VALIDITY 項目、MINIMIZE IMPLYDEF 項目の ELEMENT、ATTLIST、ENTITY、NOTATION の各パラメタのみです。従ってこれら以外の SGML 的な制約は、XML が妥当であるか否かには無関係ということになります。
Web SGML では、文書型宣言の構文にもいくつかの変更が加えられています。
XML には直接関係ありませんが、Web SGML では文書型宣言に記述する文書型名 ― すなわち文書要素名 ― を暗黙に示すことができるようになりました。例えば、次のような記述を行えます。
<!DOCTYPE #IMPLIED
PUBLIC "-//W3C//DTD HTML 4.01//EN" >
IMPLIED は暗黙の文書型名を示す予約名です。上のような記述を行った場合、暗黙に宣言された要素型を含め、任意の要素型を文書要素として記述できます。上の例では、html 要素の代わりに body 要素や p 要素を文書要素としても構わないわけです。つまり次の例は妥当になっています。
<!DOCTYPE #IMPLIED
PUBLIC "-//W3C//DTD HTML 4.01//EN" >
<p>sample</p>
なお IMPLIED キーワードを用いた場合、文書要素の開始タグを省略したり、空の開始タグとして記述したりすることはできません。従って、結果的には一番最初に出現する要素が文書要素とみなされます。
この構文は、SGML 宣言の最小リテラルが "ISO 8879:1986 (WWW)"
なら、他の前提を必要とせずに記述できます(上記の例の通り HTML 4.01 でも可能です)。ただし、XML の構文ではこのような記述は行えないことになっています。
前書きというのは文書型宣言のことです。Web SGML では、LINK EXPLICIT NO
かつ CONCUR NO
の文書において、IMPLYDEF DOCTYPE YES
または IMPLYDEF ELEMENT YES
が宣言されている場合、文書型宣言を省略することができます。
文書型宣言が省略された場合には、次の暗黙の文書型宣言がなされたものと見なされます。
IMPLYDEF DOCTYPE YES
の場合<!DOCTYPE #IMPLIED SYSTEM >
IMPLYDEF DOCTYPE NO
の場合<!DOCTYPE #IMPLIED >
この <!DOCTYPE foo >
という記述は奇異なものに思われますが、文書型宣言が外部サブセットを持たず、内部サブセットが空であるような場合には、これで何ら問題ありません。
# なお定義によれば、内部サブセットを示す dso [
及び dsc ]
が省略された場合、内部サブセットは存在しないのではなく空になっているということになっています。逆に言えば、dso と dsc が省略されているのは内部サブセットが空であるという特殊なケースである、ということになるかも知れません。
妥当性を検証する場合は IMPLYDEF DOCTYPE NO ELEMENT NO
であり、このような文書型宣言の省略は行えません。一方、妥当性を検証せず、単なる整形式 XML としてパージングを行う場合は IMPLYDEF DOCTYPE NO ELEMENT YES
ですから、問題なく文書型宣言を省略することができます。
なお Comparison of SGML and XML の記述では IMPLYDEF DOCTYPE YES ELEMENT YES
となっていますが、これも前述同様 N1955 の記述を元にしたものと思われます。パージングを簡潔にする目的でこのような定義になっていたのかも知れませんが、XML 勧告の定義からすると、DOCTYPE YES
を宣言するのは不適切であると思われます。
# XML Schema や RELAX NG による検証は <!DOCTYPE #IMPLIED SYSTEM >
と見なすことができるような気もしますが…どうなんでしょう?
<?xml version="1.0" ?>
<doc xml:lang="ja">
<title>簡単な整形式 XML 文書の例</title>
<p>これは整形式 XML 文書の例です。</p>
<p>"&" などの実体参照も記述できます。</p>
</doc>
定義済みデータ実体や暗黙のデフォルト宣言の概念と併せて考えると、パーザは上の整形式 XML 文書を次のように見なすということになります。
<?xml version="1.0" ?>
<!DOCTYPE doc [
<!ENTITY amp "&#38;" >
<!ENTITY lt "&#60;" >
<!ENTITY gt "&#62;" >
<!ENTITY quot "&#34;" >
<!ENTITY apos "&#39;" >
<!ELEMENT doc - O ANY >
<!ATTLIST doc
xml:lang CDATA #IMPLIED
>
<!ELEMENT title - O ANY >
<!ELEMENT p - O ANY >
]>
<doc xml:lang="ja">
<title>簡単な整形式 XML 文書の例</title>
<p>これは整形式 XML 文書の例です。</p>
<p>"&" といった具合に、一部の実体参照も記述できます。</p>
</doc>
このように、文書型宣言すらない整形式 XML 文書も、完全宣言済みでこそないものの厳密に型妥当になっているわけです。換言すれば、このような文書は暗黙の宣言を実際に記述するだけで妥当な XML になります。おかしな文書型宣言さえ書かなければ、整形式 XML は勝手に型妥当になっているわけです。
なお、XML は上で示した他にも (SGML 宣言では表現できないような) 様々な制約を持っています。
例えば「注釈宣言内には注釈を一つしか書けない」「XML 宣言の前には一切の文字が禁じられている」「内部サブセットではマーク宣言の許された位置にしかパラメタ実体参照を記述できない」といった特殊な制約は、SGML 宣言の項目では表現されません。
こういった細かな(例外的)制約については、SGML 宣言に追加された SEEALSO という項目で設定することになっています。SEEALSO は see also で、この記法も参照せよ
という意味です。XML の SGML 宣言では、次のように記述されています。
SEEALSO "ISO 8879//NOTATION Extensible Markup Language (XML) 1.0//EN"
この記述によって、前記のような制約を指定することができるようになっているわけです。