2. Well-Formed XML の仕組み

目次

2.1. 妥当と整形式

前章では Web SGML 適応で新たに追加・変更された定義のうち、妥当な XML の定義を理解するために必要なものについて解説しました。しかし、いわゆる整形式 XML 全般の定義を理解するためには、もう少し必要となる知識があります。以下では妥当な XML と整形式 XML の差違についても触れながら、整形式 XML の定義について解説していきます。

なお、妥当/整形式という区別は作者によってなされるものではありません。この区別は、文書の利用者が妥当性検証を行う SGML 宣言を用いるか否かによって決定されるものです。パーザに妥当性検証用の SGML 宣言が与えられれば、文書は妥当な XML として扱われますし、単に整形式性を検証するだけの SGML 宣言が与えられれば、文書は整形式 XML として扱われるのです。

まずここで、改めて「妥当」「整形式」という語の定義について確認していきます。

2.1.1. 妥当

妥当な XML 文書とは、整形式 XML 文書のうち特に型妥当であり完全宣言済みであるものを言います。

型妥当であるとは、文書インスタンスが文書型宣言の定義 ― 例えば要素の内容モデルや属性の宣言値 ― に完全に適合しているということです。詳しくは後述しますが、この文書型宣言の定義というのは暗黙のデフォルト宣言を含みます。

また完全宣言済みであるとは、文書インスタンスに現れる全ての要素や属性が DTD で明示的に宣言されていることを言います。これは、記述された要素や属性が宣言されてさえいればよく、内容モデルや宣言値に則った記述が行われているかどうかは関係しません。

2.1.2. 整形式

そして整形式 XML 文書とは、文書インスタンスが完全タグ付きであり、かつ完結記憶である適合 SGML 文書を言います。

完全タグ付きとは、全ての要素に終了タグと空でない開始タグが記述されており、全ての属性指定に属性名が記述されていることを言います。これは DATATAG NORANK NOOMITTAG NOSHORTTAG STARTTAG EMPTY NOSHORTTAG ATTRIB OMITNAME NOEMPTYNRM YES を満たすということと等価です。

また完結記憶であるとは、全ての要素(及びマーク区間)がそれの開始したのと同じ実体の中で終了することを言います。例えば、次の文書は完結記憶ではありません。

例1
<!DOCTYPE doc [
<!ELEMENT doc (para)+ >
<!ELEMENT para (#PCDATA) >
<!ENTITY STAG-para "&#60;para&#62;" >
<!ENTITY ETAG-para "&#60;/para&#62;" >
]>
<doc>
  &STAG-para;…文章…&ETAG-para;
</doc>

この例では、para 要素は実体 "STAG-para" で始まり、実体 "ETAG-para" で終了してしまっているわけです。旧来の SGML ではこのような構文が許されていますが、XML には整形式でなければならない(完結記憶でなければならない)という制約がありますから、上のような記述は不可ということになります。

整形式という概念を学ぶ上で最も注意が必要なのは、整形式 XML は型妥当でなくとも良いという点です。これは言い方を換えれば「型妥当でない文書も正しい XML 文書と見なされる」ということを意味します。

ここで、改めて整形式 XML というものを三種類に大別してみます。

  1. 型妥当であり、かつ完全宣言済みであるもの
  2. 型妥当であるが完全宣言済みではないもの
  3. 型妥当でないもの

型妥当かつ完全宣言済みである XML 文書とは取りも直さず妥当な XML 文書のことですが、妥当でない整形式 XML についても型妥当であるか否かの区別があることは覚えておいて下さい。

# なお、妥当でないのに型妥当であるような状態が有り得るのか、ということに関しては、後で詳しく述べます。それがこの "整形式 XML の仕組み" の趣旨です。

2.2. 表明

さて、前節で触れた型妥当でない整形式 XML 文書とは、例えば次のようなものです。

例2
<?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 項目です。

2.2.1. OTHER VALIDITY 項目

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 宣言(完全タグ付きの項参照)によって表現可能であるからだと思います。

2.2.2. OTHER ENTITIES 項目

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 を宣言します。

2.3. 定義済みデータ文字実体

旧来の 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 という定義の場合、"&amp;"の置換テキストは"&"ではなく"&#38;"となることに注意して下さい)。

<!ENTITY amp  "&#38;#38;" >
<!ENTITY lt   "&#38;#60;" >
<!ENTITY gt   "&#38;#62;" >
<!ENTITY quot "&#38;#34;" >
<!ENTITY apos "&#38;#39;" >

XML で、これら五つの実体参照が実体宣言なしでも記述できるのは、この機構によるものです。

なお、上の定義は Valid XML・Well-Formed XML 共通のものです。従って、妥当な XML でも "&amp;" や "&lt;" といった実体参照は宣言せずに記述できることになります。ただし、XML 勧告には相互運用性のためには、妥当な XML 文書ではこれらの実体も他の実体同様に宣言すべきであるという記述があり、XHTML 1.1 などでもこれらの実体は旧来通りに宣言されています。

2.4. 暗黙のデフォルト宣言

文書型宣言の記述されていない整形式 XML 文書は、屡々「DTD が存在しない」XML であると解説されます。しかし、SGML 的にはこのような文書にもきちんと DTD (と文書型宣言)が存在しますし、実は文書型宣言のない整形式 XML 文書は常に型妥当にもなっています。

この「文書型宣言がないにも関わらず型妥当である」という状態を可能にしているのが、Web SGML で導入された暗黙のデフォルト宣言という機構です。

暗黙のデフォルト宣言に関する定義は、SGML 宣言の MINIMIZE IMPLYDEF 項目で行います。IMPLYDEF 項目には ELEMENT、ATTLIST、DOCTYPE、ENTITY、NOTATION の五つのパラメタがあります。

2.4.1. ELEMENT パラメタ

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 が指定されたものと見なされ、旧来通り暗黙の宣言は行われません。

*1: 直接再帰要素

同じ型の要素を子要素とする要素を直接再帰要素と言います。

<!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>

2.4.2. ATTLIST パラメタ

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 >
]>

2.4.3.DOCTYPE パラメタ

DOCTYPE パラメタは、暗黙の文書型宣言が外部サブセットに宣言を持つことの可否について、YES/NO で設定します。詳しくは後述の省略された前書きを参照して下さい。

2.4.4.ENTITY パラメタ

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 processorENTITY NOENTITY NOENTITY NO
non-validating processorENTITY NOENTITY 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 のどちらかの記述(ないし、その記述に対する筆者の解釈)に不備があるように思います。

2.4.5. NOTATION パラメタ

同様に、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 が妥当であるか否かには無関係ということになります。

2.5. 暗黙の文書型宣言

Web SGML では、文書型宣言の構文にもいくつかの変更が加えられています。

2.5.1. 暗黙の文書型名

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 の構文ではこのような記述は行えないことになっています。

2.5.2. 省略された前書き

前書きというのは文書型宣言のことです。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>"&amp;" などの実体参照も記述できます。</p>
</doc>

定義済みデータ実体暗黙のデフォルト宣言の概念と併せて考えると、パーザは上の整形式 XML 文書を次のように見なすということになります。

<?xml version="1.0" ?>
<!DOCTYPE doc [

<!ENTITY amp  "&#38;#38;" >
<!ENTITY lt   "&#38;#60;" >
<!ENTITY gt   "&#38;#62;" >
<!ENTITY quot "&#38;#34;" >
<!ENTITY apos "&#38;#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>"&amp;" といった具合に、一部の実体参照も記述できます。</p>
</doc>

このように、文書型宣言すらない整形式 XML 文書も、完全宣言済みでこそないものの厳密に型妥当になっているわけです。換言すれば、このような文書は暗黙の宣言を実際に記述するだけで妥当な XML になります。おかしな文書型宣言さえ書かなければ、整形式 XML は勝手に型妥当になっているわけです。

2.6. 追加要件

なお、XML は上で示した他にも (SGML 宣言では表現できないような) 様々な制約を持っています。

例えば「注釈宣言内には注釈を一つしか書けない」「XML 宣言の前には一切の文字が禁じられている」「内部サブセットではマーク宣言の許された位置にしかパラメタ実体参照を記述できない」といった特殊な制約は、SGML 宣言の項目では表現されません。

こういった細かな(例外的)制約については、SGML 宣言に追加された SEEALSO という項目で設定することになっています。SEEALSO は see also で、この記法も参照せよという意味です。XML の SGML 宣言では、次のように記述されています。

SEEALSO "ISO 8879//NOTATION Extensible Markup Language (XML) 1.0//EN"

この記述によって、前記のような制約を指定することができるようになっているわけです。

この文書のステータス

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