第14回 要素型宣言と要素内容でDTDを理解する

XML 1.0は、1998年にW3Cから勧告として公開された。当然中身は英語で、しかもEBNFと呼ばれる式によって重要な部分が記述してある。この連載では、XML 1.0を深く理解するために、そのXML 1.0勧告の最新版「Extensible Markup Language (XML) 1.0 (Second Edition)」をだれでも分かるように、やさしく読み解きながら解説していくことを目指している。(編集局)

川俣 晶
株式会社ピーデー
2003/10/7



要素型宣言と要素内容を読む
今回の主な内容
要素型宣言と要素内容を読む
要素型宣言
  要素型宣言の概要
  要素型宣言を持たない要素型を要素型宣言から参照
  要素型宣言の定義
 「木」構造であるDTDの限界と「生け垣
  要素型宣言の例
要素内容
  要素内容の定義
  要素−内容モデルのEBNF表記
  生成規則の説明
  生成規則の適用
  妥当性制約
  要素内容モデルの例

 前回は、XML1.0勧告の中で、「3 Logical Structures(3 論理構造)」から「3.1 Start-Tags, End-Tags, and Empty-Element Tags(3.1 開始タグ、終了タグおよび空要素タグ)」までを読んだ。ここには、XMLを学ぶ者ならだれでも最初に出合う要素や属性についての直接的な説明があり、抽象的な概念や、細かい文字の扱いなどに比べれば、とてもエキサイティングといえる。

 しかし、本当にエキサイティングなのは、XMLが表現するより深いモデルなどについての話題かもしれない。今回は、「3.2 Element Type Declarations(3.2 要素型宣言)」から、「3.2.1 Element Content(3.2.1 要素内容)」までを読んでいく。ここは、DTDに関する機能についての説明であるため、少しつまらないと感じる読者もいるかもしれない。だが、DTDに含まれる概念の多くは、RELAX NGやXML Schemaといった新しいスキーマ言語でもそのまま役立つものである。構文は時代遅れになっても、概念はずっと生き続けているので、これを学ぶことは意義があるといえる。

 そして、新しいスキーマ言語とDTDの本質的な相違はどこにあるのか、という点にも今回は踏み込む。そういうXMLが表現するモデルについての話題に入り込んでいくと、XMLに対するまた新しい印象が得られるかもしれない。今回説明している「」と「生け垣」の相違を理解することは、どういうときにDTDでは表現力不足になり、新しいスキーマ言語が必要とされるかの判断基準の1つを得ることにもつながるのである。

編集注:この連載では、XML 1.0勧告であるW3Cの「Extensible Markup Language (XML) 1.0 (Second Edition)」(英語)を参照し、その日本語訳として、日本工業規格 JIS X 4159:2002(リンク先は該当規格の原案ですが、最終版とほぼ同等の内容です)を参照しています。本文中のピンクの地の部分は、XML 1.0勧告の原文を示しています。

要素型宣言

 さて今回は、「3.2 Element Type Declarations(3.2 要素型宣言)」に入る。これは、そのタイトルのとおり、要素型宣言を定義している個所である。要素型宣言は、ある要素型の要素が取り得る子の条件を制約するために、DTDに記述されるものである。妥当なXML文書には必須のものではあるが、大多数のXML利用者が最初に接する整形式のXML文書には必須ではないものである。それ故に、要素型宣言を知らずにXMLを使ってしまう人や、難度が高いと思う人もいるかもしれないが、これはXMLの本質を考える糸口にもなる重要な機能ともいえる。新しい世代のスキーマ言語の特徴である「木」ではない「生け垣」(で説明する)という概念を把握するにも、この部分をよく読んでおく必要がある。

要素型宣言の概要

 さて、最初は要素型宣言についての一般的な説明から入る。

The element structure of an XML document may, for validation purposes, be constrained using element type and attribute-list declarations. An element type declaration constrains the element's content.

妥当性を保証するため、要素型宣言および属性リスト宣言を用いてXML文書の要素の構造に制約を加えることができる。要素型宣言は、要素の内容についての制約とする。

 「妥当性を保証するため(for validation purposes)」とは、妥当なXML文書である状態を成立させるために、と理解してもよい。前回の「妥当性制約: 要素の妥当性」で、「要素が妥当とは、その要素型とマッチするNameを持つ宣言(elementdeclにマッチするもの)が存在し(以下略)」と書かれているが、この宣言が要素型宣言である。つまり、妥当なXML文書であるためには、文書に含まれるすべての要素の要素型に対応する要素型宣言が必要なのである。ただし、現実的にはこの説明は逆で、通常はDTDの記述された要素型宣言に存在する要素型のみを使って文書を記述することがほとんどである。

 この後に、さらにもう1つの文章が続いている。ここで言及している「要素の内容についての制約」とは、要素の内容に何を書いてよく、それがどのような順番でなければならないかを制約するということである。例えば、子要素として、要素Aと要素Bを、A→Bの順番で記述することのみを許す、といった制約を課すことができる。そのために使われるものが、要素型宣言ということになる。

要素型宣言を持たない要素型を要素型宣言から参照

 さて、次は、要素型宣言を持たない要素型を要素型宣言から参照する場合についての話である。

Element type declarations often constrain which element types can appear as children of the element. At user option, an XML processor may issue a warning when a declaration mentions an element type for which no declaration is provided, but this is not an error.

要素型宣言は、要素の子として出現可能な要素型について、制約を加えることが多い。利用者の任意選択によっては、要素型宣言を持たない要素型がほかの要素型宣言によって参照されれば、XMLプロセサは警告を出してもよいが、これは誤りとはしない。

 ここではまず、要素型宣言は、要素の子要素について制約することができ、そのように使われることが多いという状況説明から入っている。それを踏まえたうえで、次の重要な文章につながる。ここで「At user option(任意選択)」という言葉が出てくるが、これは「1.2 Terminology(1.2 用語定義)」で定義された言葉であることを思い出してほしい。定義を以下に再掲する。

適合するソフトウェアは、記述されたとおりに振る舞ってもよい(may)、または振る舞わなくてはならない(must)(文中の助動詞による)。そのとおりに振る舞う場合は、記述された振る舞いを選択または拒否する手段を利用者に提供しなければならない。

 この場合、文中の助動詞はmayであるので、「適合するソフトウェアは、記述されたとおりに振る舞ってもよい」と解釈する。つまり、「要素型宣言を持たない要素型がほかの要素型宣言によって参照されれば、XMLプロセッサは警告を出してもよい」というように振る舞うようにしてもよいが、それは選べるようにしなければならないわけである。

 さて、ここで、「要素型宣言を持たない要素型がほかの要素型宣言によって参照されれば」という部分についても深く読み込んでみよう。すでに述べたとおり、妥当性制約を満たすためには、XML文書中のすべての要素の要素型に対応する要素型宣言は必須である。それ故に、要素型宣言のない要素型の要素を使うことは、妥当なXML文書では一切できないことになる。それなのに、ここで「要素型宣言を持たない要素型」の話が出てくる理由はいったい何だろうか。

 具体的にいえば、XML文書に出現しない要素の要素型については、要素型宣言がなくてもよい、ということである。例えば、要素型宣言が、ある要素の子要素に要素Aと要素Bの記述を許している場合、要素Aや要素Bについての要素型宣言がなくても、それは誤りとはしない、ということである。しかし、要素Aを含むXML文書を妥当とする場合には、要素Aについての要素型宣言は必須となる。その場合、要素BがXML文書に含まれていなければ、要素Bの要素型宣言は必須ではない。そして、そのような「要素型宣言を持たない要素型」があるとき、それを警告するかどうかは、選択の余地が与えられているわけである。どう選択した場合でも、「要素型宣言を持たない要素型」があることは、誤りとはされない。

要素型宣言の定義

 さて、次は、要素型宣言のEBNF定義である(EBNFの詳細については、「第2回 XML勧告読解に必須のEBNF」を参照)。

[Definition: An element type declaration takes the form:]

Element Type Declaration
[45]    elementdecl    ::=    '<!ELEMENT' S Name S contentspec S? '>' [VC: Unique Element Type Declaration]
[46]    contentspec    ::=    'EMPTY' | 'ANY' | Mixed | children

 ここでは、まず、要素型宣言という用語についての定義から始まる。要素型宣言は次の形式をとる、としているが、「次の形式」とあるとおり、この文章は実質的な定義を含んでいない。定義内容は、次の、生成規則45と46になる。

 生成規則45は、要素型宣言そのものを示す。まず“'<!ELEMENT'”という文字列があり、それに続いて、空白文字(S)があり、生成規則Nameがあり、空白文字(S)があり、生成規則contentspecに当たるものが記述され、そして、省略可能な空白文字(S?)に続いて、“'>'”を記述して終わる。そして、Unique Element Type Declaration(要素型宣言の一意性)という妥当性制約が付いている。生成規則contentspecはこの次に出てくる生成規則46である。ここで注意することは、“'<!ELEMENT'”という部分である。これらの文字列は、一続きの文字列として記述されていることから分かるとおり、途中に空白文字を入れることはできない。例えば、“<! ELEMENT”というように途中に空白文字を入れると、構文に適合しないことになる。

 次は、生成規則46である。これは、文字列“'EMPTY'”、文字列“'ANY'”、生成規則Mixed、生成規則childrenのどれか1つ、ということを意味する。“'ANY'”は、前回「宣言がANYにマッチし」として言及したもの(内容にどのようなものを記述してもよい)、“'EMPTY'”は、前回「EMPTYというキーワード」として言及したもの(内容に何も含まない空要素)である。それらのキーワードは、この位置(生成規則contentspecに当たる位置)に記述すべきものであったわけである。残りの2つは、それぞれ、Mixedが混合内容、childrenが要素内容に対応する。混合内容と要素内容は、この後に説明が行われる。

「木」構造であるDTDの限界と「生け垣」

 要素型宣言のEBNF定義の後に普通の文章が続く。

where the Name gives the element type being declared.

   Validity constraint: Unique Element Type Declaration
   No element type may be declared more than once.

Nameは宣言されている要素の型を示す。

Unique Element Type Declaration(要素型宣言の一意性)と名付けられた妥当性制約は、1つの要素型を2回以上宣言できない。

 最初の行は生成規則45に含まれるNameについての説明である。前回に見たように、要素の型(要素型)とは名前であるので、Nameに対応する名前がそれに対応するわけである。1つの要素型宣言には、1つの名前を記述することができ、それが要素型に対応する。ある特定の名前の要素は、すべて、この要素型宣言によって制約を課されるというわけである。これは、次の文章と併せて、重要なDTDの特徴を示している。

 最後に、妥当性制約が記述されている。これは、ある名前の要素に対する制約は複数記述できないことが示されている。例えば、1つのDTDの中に、人物情報の要素の中で肩書きを示すtitle要素と、書籍情報の要素の中で書籍名を示すtitle要素があるような場合を想定すると、この2種類のtitle要素は同じ要素型であると見なされるため、たとえ内容の制約が異なっていても、別々の要素型宣言を記述することはできない。これは前の文章と併せて、DTDは名前を元にした単純な木構造しか持てないことを示している。つまり、要素の名前が決まると、その内容には必ず同じパターンが出現することが強制されてしまうのである。

 これは不便な特徴であるため、「」に代わって出てきたのが「生け垣(hedge)」という考え方である。生け垣とは木が複数存在する状況を示している。つまり、ある名前の要素の内容のパターンが1つの木であるとすれば、複数の木が存在することを許容するわけである。それにより、例えば出現する文脈が異なる場合に、異なる内容を制約することが可能になる。なぜDTDが時代遅れで、新しいスキーマ言語が必要とされたかについて、構文がXML文書ではない、名前空間に対応していない、といった点が説明されることが多いが、実際にはこのような目立たないが重要なポイントも変化しているわけである。むしろ、構造上、最も本質的にDTDでは機能不足である部分が、これであるとすらいえる。XMLのスキーマ言語の諸問題に興味を持つ場合は、ぜひ把握しておきたい問題である。

要素型宣言の例

 さて、次は、要素型宣言の例である。

Examples of element type declarations:

<!ELEMENT br EMPTY>
<!ELEMENT p (#PCDATA|emph)* >
<!ELEMENT %name.para; %content.para; >
<!ELEMENT container ANY>

 ここまで説明した知識では読み切れない部分もあると思うが、一応、簡単に説明すると、最初は、brという名前の要素型の内容は空である(空要素である)という制約を記述している。(X)HTMLのbr要素を意識したものといえるだろう。2番目は、pという名前の要素型の内容は、文字データまたはemph要素のどちらかを0回以上繰り返したものと制約する意図を示している。これは後で出てくる混合内容となっている。3番目は、パラメタ実体を使った例である。%name.para;は名前の文字列に置き換えられ、%content.para;は内容を示す文字列に置き換えられる。このようにパラメタ実体を使って、名前や制約を直接記述しないのは、DTDを記述する場合の定番のテクニックである。これによって、後からDTDをカスタマイズして使うことが可能となる。4番目は、containerという名前の要素型の内容には何があってもよい(しかし要素型宣言のない要素を記述することはできない)という意図を示している。

要素内容

 すでに示したように、要素型宣言では、要素内容の制約をEMPTY、ANY、要素内容、混合内容の4種類の中から選ぶことができる。「3.2.1 Element Content(3.2.1 要素内容)」では、その中の要素内容についての説明が行われている。

要素内容の定義

 まず、要素内容という言葉の定義から始まる。

[Definition: An element type has element content when elements of that type must contain only child elements (no character data), optionally separated by white space (characters matching the nonterminal S).][Definition: In this case, the constraint includes a content model, a simple grammar governing the allowed types of the child elements and the order in which they are allowed to appear.] The grammar is built on content particles (cps), which consist of names, choice lists of content particles, or sequence lists of content particles:

[定義:ある型の要素が、必ず子要素だけを含み(文字データを含まないs)、それらの間には空白(非終端記号Sにマッチする文字)だけしか現れないとき、その要素型は、要素内容を持つという。][定義:この場合、内容モデルが制約となり、内容モデルは、子要素の型および子要素の出現順序を制御する簡単な文法とする。]この文法は、内容素子(cp)から成り、内容素子は、名前、内容素子の選択リストまたは内容素子の列リストから構成される。

 この段落には、element content(要素内容)の定義と、content model(内容モデル)に関する定義と、もう1つの文章が含まれている。まず、要素内容の定義の文章では、要素の子に文字データがなく、要素だけである場合、「要素内容を持つ」となる。空白はあってもよく、また、ここでは言及されていないが、コメントなどもあってよい。文字データを含むものは、要素内容ではなく、この後で説明される混合内容に該当する。

 次の文章は、content model(内容モデル)に関する定義である。少し文章が込み入っているが、順番に整理しよう。まず、内容モデルとは、「子要素の型」および子要素の「出現順序」を制御するものである。子要素の型とは、どんな名前の要素(どんな要素型の要素)が出現するかを示す。そして、出現順序とは、それらの要素を記述する順番に関する情報を意味する。例えば、要素Aの次に要素Bを書くことは許すが、要素Bの次に要素Aを書くことは許さない、といった制約は、出現順序に関する情報である。それを制御するための簡単な文法が、内容モデルと呼ばれるわけである。具体的な文法の書き方そのものは、この後で出てくる。

 そして、この内容モデルは、文字データに関する制約を含まないという点で、要素の内容の制約とイコール視することはできない。しかし、要素内容に限っていえば、内容モデルが、要素の内容の制約とイコールになるわけである。逆にいえば、混合内容の場合は、イコールにならないということである。

 さて、最後の文章に進もう。これはいかなる用語の定義でもない。内容素子(cp)とは、この後に出てくる生成規則48(cp)を意味する。そしてこれは、生成規則48(cp)を言葉で書いたものに極めて近い。この生成規則内では、名前がName、内容素子の選択リストがchoice、内容素子の列リストがseqに該当する。Nameの意味はすでに解説しているが、choiceとseqはこの後で解説する。

要素−内容モデルのEBNF表記

 次は、EBNF表記の生成規則である。

Element-content Models

[47]    children    ::=    (choice | seq) ('?' | '*' | '+')?
[48]    cp    ::=    (Name | choice | seq) ('?' | '*' | '+')?
[49]    choice    ::=    '(' S? cp ( S? '|' S? cp )+ S? ')' /* */
/* */
[VC: Proper Group/PE Nesting]
[50]    seq    ::=    '(' S? cp ( S? ',' S? cp )* S? ')' /* */
[VC: Proper Group/PE Nesting]

 まず、生成規則47(children)は、要素内容そのものに対応する。これは前半と後半の2つの部分に分けて考えられる。前半は、(choice | seq) という部分で、生成規則choiceか、seqのどちらかを示す。これらは、すぐ後に定義が出てくるので、ここでは詳細を調べないで先に進もう。後半は、('?' | '*' | '+')?という部分で、'?'、'*'、'+'のいずれかの記号か、あるいはそれを記述しないという選択をすることができる。これらの記号の意味は、この後で説明される。

 次に生成規則48(cp)だが、これはすでに出てきた内容素子である。これは生成規則47(children)とよく似ている。前半部分に、Nameがあることを除くと、まったく同じである。しかし、立場はまったく異なる生成規則であることに注意が必要である。このNameについては、後の文章で説明が行われているので、ここでは説明せず、先に進もう。

 次は、生成規則49(choice)である。少し長く込み入ったEBNF式が記述されているが、その意図は簡単である。(内容素子1|内容素子2|……|内容素子n)のような文字列を許すための式である。例えば、(りんご|みかん|いちご)のようなものが、これに当たる。前後のカッコは必ず記述しなければならず、内容素子は少なくとも2個なければならない。名前の間は、“|”記号で区切られる。そして、個々の項目の間には空白文字を書くことができ、書かないこともできる。ここで気になるのは、名前は少なくとも2個という条件である。最初のcpと、1回以上の繰り返しを示す“+”記号の付いたカッコ内のcpと合わせて、少なくとも2個は記述しなければこの式は成立しない。とすると、1種類の内容素子だけを記述する(りんご)のような文字列は、生成規則49(choice)にマッチしないことになる。しかし、このような文字列を記述しても、構文エラーにならない。それは、この式は生成規則49(choice)にはマッチしないが、生成規則50(seq)にはマッチするためである。このような定義は、本来意図した意味を考えれば、自然な解釈であることが分かるだろう。生成規則49(choice)は選択を意図したものであり、生成規則50(seq)はシーケンス(列)を意図したものである。1個だけから成る列はあり得るが、1個しかない対象は選択の余地がないので、選択の対象にはならないのである。

 もう1つ確認しておきたいことは、この生成規則49(choice)と、次の生成規則50(seq)には、妥当性制約Proper Group/PE Nesting(グループおよびパラメタ実体が厳密な入れ子を成していること)が付いていることである。

 次の生成規則50(seq)は、生成規則49(choice)とよく似ている。異なるのは、区切り記号として“|”ではなく“,”が使われていることと、繰り返しを示す記号が“+”ではなく、“*”になっていることである。区切り記号の相違によって、こちらの方は、(りんご,みかん,いちご)のような文字列を許すことになる。また、繰り返し記号が“*”であることから、この生成規則は、内容素子が1つである(りんご)のような文字列を許す。

生成規則の説明

 次は、これらの生成規則の詳しい説明に入る。

where each Name is the type of an element which may appear as a child. Any content particle in a choice list may appear in the element content at the location where the choice list appears in the grammar; content particles occurring in a sequence list must each appear in the element content in the order given in the list. The optional character following a name or list governs whether the element or the content particles in the list may occur one or more (+), zero or more (*), or zero or one times (?). The absence of such an operator means that the element or content particle must appear exactly once. This syntax and meaning are identical to those used in the productions in this specification.

Nameは、子として出現してよい要素の型を示す。この文法で選択(choice)リストが現れる位置では、選択リスト内のいずれの内容素子も要素内容の中に現れてよく、列(sequence)リストに現れる内容素子は、リストで指定する順番のとおりに、要素内容に現れなければならない。名前またはリストの後に出現する任意選択の文字は、要素またはリスト内の内容素子が、1回以上任意の回数(+)、0回以上任意の回数(*)または0回もしくは1回(?)出現可能なことを規定する。この演算子(operator)がない場合は要素または内容素子が正確に1度だけ現れなくてはならないことを意味する。ここで示す構文および意味は、この規格における生成規則で用いるものと同一とする。

 要素型宣言の生成規則45(elementdecl)に出てきたNameも要素の型を示しているが、冒頭の文はそれと対応するものといえる。ここでいうNameが参照する先は、生成規則45(elementdecl)に記述されるNameになるのである。

 次に、生成規則49(choice)と、生成規則50(seq)の意味するところを説明している。生成規則49(choice)は、列挙した内容素子のどれが要素内容に出現してもよいのである。生成規則50(seq)のseqは列(sequence)を略した表記である。そして、これは列挙した内容素子が書かれたとおりの順番で、要素内容に出現することを示している。

 次は、生成規則47(children)48(cp)の後半部分に出現する記号の意味を説明している。“+”は1回以上の任意回数の繰り返し、“*”は0回以上の任意回数の繰り返し、“?”はオプションであり、それがあってもなくてもよいことを示す。

 次の文は、これらの記号が記述されなかった場合の解釈を説明している。演算子とは、+、*、?の記号を示している。これらがない場合は、対象となるものが、1回だけ出現しなければならないのである。2回以上出現してはならないし、出現しないのも許されない。

 次は、これらの記号の意味は、実はEBNFで使われる記号の意味と同じということを説明している。この連載で最初に説明したEBNFをすでに把握していれば、これらの記号の意味は説明しなくてもすぐに分かるだろう。

生成規則の適用

 次は、これらの生成規則を、どう適用していくかについて説明されている。

The content of an element matches a content model if and only if it is possible to trace out a path through the content model, obeying the sequence, choice, and repetition operators and matching each element in the content against an element type in the content model. For compatibility, it is an error if an element in the document can match more than one occurrence of an element type in the content model. For more information, see E Deterministic Content Models.

要素の内容が内容モデルにマッチするのは、列、選択および繰返し演算子に従って、内容の中の要素と内容モデル内の要素型とをマッチさせながら、内容モデル内の1つのパスをたどれるときに限る。互換性のため、文書内の要素が、内容モデルにおける要素型の複数の出現位置とマッチすることは、誤りとする。詳細な規定については、E. 決定的内容モデルを参照。

 冒頭の文は、要素の内容が内容モデルにマッチすることの条件を記述している。さまざまな演算子に従って、内容の中の要素と内容モデル内の要素型がマッチすれば、要素の内容が内容モデルにマッチするというのは、ある意味で当然期待されることである。

 それよりも重要なことは、「1つのパスをたどれるときに限る」という部分である。1つのパスをたどれる、ということは、ある要素に到達する要素型宣言の組み合わせが1種類しか存在しないことを示す。これが2種類以上あるということは、「木」のモデルで考えると、根から分かれながら伸びた枝が、途中で再び1つに合わさる状況が発生することを意味する。1度分かれた枝が1つになるようなことは、「木」のモデルではあり得ないことである。そのため、「木」のモデルのDTDでは、このような状況が許されない。しかし、異なる解釈は、別の木で実現されると考える「生け垣」のモデルなら、これが許される状況があり得るわけである。

 次の「互換性のため」とは、SGMLとの互換性を維持するために必要とされている条件であることを示す言葉である。「内容モデルにおける要素型の複数の出現位置とマッチする」というのは、例えばこういう状況を示すのだろう。(A?,A?)というような内容モデルがあるとき、要素Aが1つだけ内容に記述されていたとする。その場合、この要素Aは、内容モデルの最初のAであり、2番目のAが省略される場合と、最初のAが省略され、2番目のAにマッチする場合が考えられる。こういう状況は、誤りとする、というわけである。

 しかし、この条件が、「互換性のため」に記述されている点には注意を払う価値がある。互換性を意識しない場合は、これを誤りにしない使い方もあり得る、ということである。スキーマとは文書の妥当性を判断するためだけに存在するものだとすれば、複数の解釈があり得る場合でも、1つ以上の解釈で妥当と判断できれば、その文書は妥当であるとする考え方も当然あり得るわけである。しかし、DTDにおいては、互換性のため、そのような考えは採られていない。

妥当性制約

 次は妥当性制約について記述している。

Validity constraint: Proper Group/PE Nesting

Parameter-entity replacement text must be properly nested with parenthesized groups. That is to say, if either of the opening or closing parentheses in a choice, seq, or Mixed construct is contained in the replacement text for a parameter entity, both must be contained in the same replacement text.

妥当性制約:Proper Group/PE Nesting

パラメタ実体の置換テキストは、カッコで囲まれたグループによって、厳密な入れ子を構成しなければならない。つまり、choice、seqまたはMixedに、左小カッコまたは右小カッコのいずれか一方が パラメタ実体の置換テキストに含まれれば、他方も同じ置換テキストに含まれなければならない。

 これは、妥当性制約 Proper Group/PE Nesting(グループおよびパラメタ実体が厳密な入れ子をなしていること)について説明している。そして、より具体的な説明が次に続く。つまり、<!ELEMENT sample (abc%def;>というように記述することはできない、ということである。この場合、開きカッコに対応する閉じカッコは、パラメタ実体defの中にあることが期待されているが、同じ置換テキスト中に開きカッコと閉じカッコがないので、これは誤りとなる。

 妥当性制約に関する説明はさらに続く。

For interoperability, if a parameter-entity reference appears in a choice, seq, or Mixed construct, its replacement text should contain at least one non-blank character, and neither the first nor last non-blank character of the replacement text should be a connector (| or ,).

相互運用性のためには、choice、seqまたはMixedの中にパラメタ実体が現れた場合、その置換テキストは少なくとも1つの空でない文字を含むことが望ましく、置換テキストの最初および最後の空でない文字は接続子(|または,)でないことが望ましい。

 「相互運用性のため」とは、SGMLプロセッサで利用できる可能性を高める拘束力は持たない推奨事項である。「互換性のため」と異なり強制力はない。ここでは、choice、seqまたはMixedの中にパラメタ実体が現れる場合の推奨事項について書かれており、パラメタ実体の置換テキストには、空でない文字を含むことが望ましいとしている。また、置換テキストの最初および最後の空でない文字は“|”または“,”でないことが望ましい、としている。おそらく、大半のXML利用者がSGMLプロセッサを使うことはないと思うので、軽く読み流してもよいだろう。

要素内容モデルの例

 次は要素内容モデルの例である。

Examples of element-content models:

<!ELEMENT spec (front, body, back?)>
<!ELEMENT div1 (head, (p | list | note)*, div2*)>
<!ELEMENT dictionary-body (%div.mix; | %dict.mix;)*>

 最初の例は、いくつかのXML文書を見ながら読んでみよう。これはspecという名前の要素(要素型)は、front、body、backという3つの要素の列であり、backは省略可能であることを示している。front、body、backの3つの要素が内容に書かれた以下のような文書にマッチする。

<spec>
  <front>前書き</front>
  <body>本文</body>
  <back>後書き</back>
</spec>

 backを記述していない以下のような文書にもマッチする。

<spec>
  <front>前書き</front>
  <body>本文</body>
</spec>

 しかし、省略可能ではないfrontを記述しなければ、これはマッチしなくなる。以下はマッチしない例である。

<spec>
  <body>本文</body>
  <back>後書き</back>
</spec>

 また、これは列(seq)であるため順番を変えるとマッチしなくなる。以下はマッチしない例である。

<spec>
  <front>前書き</front>
  <back>後書き</back>
  <body>本文</body>
</spec>

 例の2番目は、div1という名前の要素(要素型)の内容は、(head, (p | list | note)*, div2*)であることを示している。これは、まずhead要素があり、次に、p、list、noteのいずれかの要素が0回以上繰り返され、最後にdiv2要素が0回以上繰り返されることを示している。

 最後の例は、パラメタ実体を使った例である。これまで見てきたように、パラメタ実体を使う場合には、いろいろな条件が付いているが、それらを守った使い方が示されている。

 さて、今回はこれで終わりである。次回は、要素内容と対を成す「3.2.2 Mixed Content(3.2.2 混合内容)」について説明していく。XMLをデータベースでしかないと思っている読者には、どうしてこんな機能があるかピンとこないかもしれないが、文章系の利用においては、混合内容は必須ともいえる重要な機能である。ぜひとも、ここを読み切って、XMLの世界の広さを感じてみよう。

連載 やさしく読む「XML 1.0勧告」


XML & SOA フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

HTML5+UX 記事ランキング

本日月間