2 A Gentle Introduction to SGML


このガイドラインによって定義されたエンコード方式は、SGMLとして知られるシステムの応用である【注3】。SGMLは、デバイスやシステムに依存せずにテクストを電子的に表現するための方法を定義する国際規格である。本章は、SGMLを知らない読者のために、SGMLの主な特徴について簡単な解説を行う。TEIにおけるSGML規格の利用についてのより技術的な説明は、28章 "Conformance" に記されている。TEIのエンコード方式に用いられるSGMLのサブセットについての、技術的な記述は、39章 "Formal Grammar for the TEI-Interchange-Format Subset of SGML" に記されている。

SGMLは、マークアップされた電子テクストを記述するための国際規格である。より詳細には、SGMLはメタ言語、この場合には、マークアップ言語を形式的に記述するための方法である。まず先に、これらの用語の定義をしておこう。

歴史的には、マークアップという言葉は、写植工やタイピストに対して、テクストがどのように印刷されるか、あるいはどのようにレイアウトされるかを指示するための注釈という意味で使われた。例えば、波下線を使って太字を表したり、特殊な記号を使って、その部分を削除するように指示したり、別のフォントで印刷するように指示する、といったことに使われた。テクストの整形や印刷が自動化されるに伴ない、マークアップという言葉は、広い意味で使われるようになり、整形や印刷、その他の処理を制御するために電子テクストに挿入される特殊なマークアップ記号全てを示すようになった。

このような背景から、ここでは、マークアップと(同義に)エンコーディングを、テクストの解釈を明示化するためのあらゆる方法、と定義する。卑近な例では、印刷されたテクストがエンコードされたものだと言える。句読点、大文字の使用、ページ上の文字の配置、語と語の間の空白さえも、マークアップの一種であると考えられる。そのようにして、どこで語が終わり、次の語が始まるのか、あるいは見出しのような全体的な構造や、従属説・文などの単純な文法的単位を、人間の読者が見つける手助けをする。コンピュータ処理のためにテクストをエンコードすることも、原理的には写本を作る時のように、暗示的なものを明示化する過程であり、利用者に対して、テクストの内容がどのように理解されるべきかを指示する過程である。

マークアップ言語という言葉は、ここでは、テクストをマークアップする際の約束事の集合を意味する。マークアップ言語は、どのようなマークアップが許されるか、どのようなマークアップが必要になるか、どのようにしてマークアップが地のテクストと区別されるか、そして、マークアップがどのような意味を持つか、ということを示さなければならない。SGMLは、これらのうち初めの三つを示すための方法である。本文書【P3 Guidelinesのこと】のような解説は、最後の点を示すためのものである。 この章は、このガイドラインを最大限活用するために必要なSGMLの知識を得るための、あまり形式的でない--規格本体に比べればずっと形式的でない---入門である。


2.1 What's Special about SGML

SGMLを他のマークアップ言語と区別する特徴は三つある。手続き的でなく記述的なマークアップを強調している点、文書型についての考え方、テクストが書かれたスクリプトを表現するいかなるシステムからも独立していること。以下では、この三つの点について簡単に述べる。更に細かい点については、2.3 "SGML Structure"(SGMLの構造)と、2.7 "SGML Entities"(SGMLの実体宣言)で述べる。

2.1.1 Descriptive Markup

記述的マークアップシステムが行うのは、マークアップ記号を用いて、文書の該当部分をカテゴリ付けするための名前を付けることだけである。<para>や\end{list}のようなマークアップ記号は、文書の該当部分を特定し、そこで「以下は段落である」あるいは「ここで箇条書きは終わり」ということを伝えるだけである。これに対し、手続き的なマークアップシステムは、文書のその場所で、どのような処理が行われるのかを定義する。「パラメタ1、b、xを用いて、手続きPARAをここで呼び出せ」あるいは「左マージンを2クワタ移動し、右マージンを2クワタ右に移動し、1行下げて、新しい左マージンに移動せよ」というものである。SGMLでは、文書に対して、ある処理を行うのに必要な指示(例えば、文書を整形するなど)は文書中に出現する記述的マークアップとは、はっきりと区別されている。通常は、独立した手続きやプログラムとして、文書の外部に集められている。

手続き的でなく、記述的マークアップにおいては同じ文書を容易に多数の異なるソフトウェアによって処理することができ、それぞれのソフトウェアが、文書中の、それぞれに必要な部分について別々の処理を適用できる。例えば、内容分析プログラムに、脚注付きテクストに埋め込まれた脚注部分を全て無視させることが可能である。また、整形プログラムに、脚注を全て取り出し、章末にまとめて印刷させることも可能である。異なる種類の処理をファイルの同じ部分に関連づけることも可能である。例えば、一つのプログラムが索引やデータベースを作成するために文書中から人名・地名を抜き出す一方で、別のプログラムが同じテクストに対して人名・地名のフォントを変えて印刷する、ということが可能である。

2.1.2 Types of Document

第二に、SGMLは文書型という概念を導入し、またそれに伴い文書型の定義を行なった。文書には、コンピュータによって処理される他のオブジェクトと同じように型(type)があると考えられる。文書の型は、その構成素と、構成素の構造によって定義される。例えば、報告書であれば、タイトルと、恐らく著者名があり、それに要旨が続き、さらに一つ以上の本文の段落から構成される、と定義されるだろう。このような形式的な定義に従えば、タイトルがないもの、本文の後に要旨が書かれたものは、人間の読者にはどれだけ報告書らしい特徴を備えているように見えても、形式的には報告書とは言えない。

もし、文書が既に知られた型のものであれば、特別なプログラム(これをパーサと呼ぶ)を使って、ある文書型であると主張される文書を処理し、その文書型に必須の要素が全て正しい順序で備えられているかを確かめることができる。さらに重要なのは、同じ文書型の異なる文書が、統一的なやりかたで処理できるということである。文書構造情報に埋め込まれた知識を利用して、より知的なやりかたで動作するプログラムを書くこともできる。

2.1.3 Data Independence

SGMLの基本的な設計目標は、ある条件に従ってエンコードされた文書が、情報の損失なく、一つのハードウェア的・ソフトウェア的環境から、別の環境へ移行できることを保証することであった。これまで述べてきた二つの特徴は、ともに抽象的なレベルにおいて、この要求に言及するものであった。三つ目の特徴は、文書が構成されるバイト(文字)列のレベルで、この要求に言及するものである。SGMLには、文字列置換のための汎用メカニズムが用意されている。つまり、文書中のある特定の文字列が、その文書を処理する時には、別の文字列に置き換えられるよう宣言するための単純な、機種非依存の仕組みがあるのである。このメカニズムを応用した分かりやすい例としては、用語法の統一が挙げられる。もう一つは、こちらのほうが重要であるが、非可搬文字に対応表情報を与えることで、かの悪名高い、異なるコンピュータシステムで互いの文字セットが理解できないという問題、あるいはどのシステムでも起こる、あるアプリケーションのために必要な全ての図形文字を利用できないという問題を対処できるということである。この文字列置換メカニズムで定義される文字列は、実体(entity)と呼ばれる。実体については、2.7 "SGML Entity" で述べる。


2.2 Textual Structure

テクストは、切れ目のない語の連鎖ではない。ましてや切れ目のないバイトの連鎖でもない。異なる目的に応じて、テクストはそれぞれ異なる単位、種類、大きさに分けられる。この文書のような散文のテクストであれば、節、章、段落、文に分けることができる。韻文であれば、篇、スタンザ、行に分けられる。印刷されたものであれば、散文や韻文の連鎖は、巻、集、ページという単位に分けられる。

このような構造上の単位は、テクスト中の位置や参照先を特定する際に頻繁に用いられる(「第10章、第2段落、三つ目の文」、「第10篇、1234行」、「412ページ」など)。しかし、このような単位は同時に、テクストを研究上の目的のための有意味な断片にさらに分割する際にも使われる(「第2節の文の長さの平均は第5節と異なるか」「自然という語は何段落おきに出現するか」「どれぐらいのページがあるか」)。これら以外の構造上の単位は、テクストの節を特徴づけるという点で、より明確に分析的である。戯曲のテクストであれば、異なる役によるそれぞれのセリフを一つの単位とみなし、舞台指導や演技をまた別の単位とみなす。そのような分析は、テクストの位置を指示する場合よりは(「第2幕のホレーショの93番目のセリフ」など)、ある役と別の役の言葉遣い、あるいは同じ役の異なる場面での言葉遣いを比較するのに役立つだろう。

同じように、散文のテクストであれば、直接話法か間接話法かの違いで別々の単位とみなしたい場合もあるだろうし、異なるスタイル(物語、論争、評論、議論)での言葉遣いの違い、あるいは著者の違い、といったものを別の単位とみなす場合もあるだろう。また、ある種の分析にとっては(文芸批評がいい例である)、印刷あるいは手書きの原文の物理的な外見が重要であることもあるだろう。逆説的なことに、このような場合、フォントであるとか、行間であるとか、空白であるといった紙の上の特徴を、記述的マークアップを使って記述しなければならない。

これらのテクスト上の構造は、複雑で予期されない形で、互いにオーバラップする。特に、紙中心の技術で実現されたテクストを扱う場合、読者は本の物理的構成と、その本に書かれた内容の論理的構造の両方を意識する必要がある。名作の多くは(例えば、SterneのTristram Shandy)、物語部分とページ分け(章や段落など)が織りなす相互作用を意識せずに、十分な鑑賞はできない。多くの研究にとって重要なのは、異なるレベルの分析の間でおこる相互作用であり、それは、例えば、どの程度まで、統語的構造と物語構造が入り交じるか、あるいは、入り交じらずに終わるか、あるいは、どの程度まで音韻構造が形態論を反映しているか、ということである。


2.3 SGML Structures

このセクションでは、SGMLによって規定されるマークアップ、つまり構造上のテクスト単位の認定のための、単純かつ一貫したメカニズムについて説明する。また、SGMLが規定する方法では、いかなるテクストにおいても、そのような単位の組み合わせが、意味のある形でどのようにテキストにも出現できるかを定義するための規則を表現する方法についても説明する。

2.3.1 Elements

要素(elements)とはSGML規格上の術語で、構造上の構成素とみなされたテクスト単位という意味で使われる。種類の異なる要素には異なる名称が与えられるが、SGMLは、要素の意味は表現せず、その要素が他の要素に対してどういう関係であるかを表現する方法を規定するだけである。すなわち、(例えば)<blort>という要素について言えることは、その実現値が<farble>という種類の要素内に起こる(あるいは起こらない)、また、それが<blortette>という種類の要素に分解されるということだけである。ここで、強調しておきたいことは、SGML規格が、テクスト要素がどういう意味を持つかということには全く関知していないことである。これは、処理するアプリケーションに依存する【注4】。要素に対して分かりやすい名称を選び、その正しい使い方を説明するのは、SGMLに適合したタグ集合(例えば、このガイドライン)の作成者が行うことである。本文書は、一つにはこれを目的とした。要素の名前には機能を機能を表したものを選択する必要から、要素の型を表す名称として、総称識別子(GI; generic Identifier)という術語が使われるようになった。 マークアップされたテクスト(文書実現値)では、それぞれの要素は、何らかの形で明示的にマークやタグが付けられていなければならない。規格では、これを行うためのいくつかの方法が規定されており、その中で最もよく使われているのは、タグを要素の先頭(開始タグ)と末尾(終了タグ)に挿入するやりかたである。開始タグと終了タグの対は、伝統的な句読法で使われるカッコや引用符と同じように、その間のテクストを囲む働きをする。例えば、テクスト中の引用のための要素は、次のようにタグ付けされる。

         ...  Rosalind's remarks <quote>This is the silliest stuff
          that ere I heard of!</quote> clearly indicate ...
上の例が示すように、開始タグは、<name>という形をとり、左不等号が、開始タグの始まりを示し、"name"の部分は、そのタグの総称識別子、そして、右不等号は、タグの終わりを示す。対応する終了タグは、</name>であり、左不等号の次にスラッシュ記号が入ることを除いて、開始タグと同一である【注5】

2.3.2 Content Models: An Example

要素は空であってもよい。つまり、要素には内容が全くなくてもよいし、単純なテクストであってもよい。しかし、通常は、エレメントは他のエレメントに埋め込まれることが多い。

ここでは、非常に単純な構造モデルを使って解説する。ある詩集(anthology)が、詩(poem)、詩のタイトル(title)、スタンザ(stanza)、行(line)だけで構成されると考えてみよう。SGMLの用語でいうと、この文書型は詩集であり、それは、いくつかの詩から構成されるということになる。それぞれの詩は、タイトルという要素と、いくつかのスタンザを含んでいる。スタンザは、さらに、行要素が埋め込まれている。このモデルに準拠したテクストを完全にマークアップしたものは、次のようになる【注6】

         <anthology>
           <poem><title>The SICK ROSE</title>
              <stanza>
                   <line>O Rose thou art sick.</line>
                   <line>The invisible worm,</line>
                   <line>That flies in the night</line>
                   <line>In the howling storm:</line>
              </stanza>
              <stanza>
                   <line>Has found out thy bed</line>
                   <line>Of crimson joy:</line>
                   <line>And his dark secret love</line>
                   <line>Does thy life destroy.</line>
              </stanza>
           </poem>

                   <!-- more poems go here    -->

         </anthology>
上の例で使われている名称は、このガイドラインで規定されている要素に与えられているものと同じではなく、また、上の文書は有効なTEI文書ではない。しかし、SGMLの基本的な概念への入門にはなるだろう。空白と改行は、見やすさのためだけに追加されたのであって、SGMLでのエンコードにおいては意味を持たない。また、
                   <!-- more poems go here    -->
という行は、SGMLの注釈であり、テクストの一部としては扱われない。

この例では、タイトルが第1スタンザの前に来るか否か、行がスタンザの中以外に現れることができるか否かということを制御する規則については何も想定されていない。そのため、冗長に見えるだろう。このような例では、要素の出現位置についての規則が明言されていないので、全ての要素の始まりと終わりが明示的にマーク付けされなければならない。しかし、実際には、タグ付けの手間を減らすための規則を決められる場合が普通である。例えば、この過剰に簡略化された詩のモデルを考えてみると、次のような規則を明言することができるだろう。

  1. 詩集はいくつかの詩を含む他には何も含まない。
  2. 詩には第1スタンザに先行して出現する一つのタイトル要素があり、タイトルとスタンザ以外の要素を含まない。
  3. タイトルの他には、詩はスタンザだけで構成される。
  4. スタンザは行だけで構成され、行はスタンザに含まれる。
  5. スタンザに続くことができるのは、他のスタンザだけであり、そうでなければ、詩集は終わる。
  6. 行に続くことができるのは、他の行だけであり、そうでなければ次の新しいスタンザが始まる。
これらの規則から推論できることは、スタンザや行の終わりを明示的にマーク付けする必要がないということである。規則2から、タイトルの終わりの位置をマーク付けする必要がないということが言える。同様に、規則3と規則1から、それぞれの詩の終わりの位置をマーク付けする必要がないということが言える。詩は、他の詩の中に出現することはできず、詩集の中に出現しなければならないからである。詩の終わりは、次の詩の始まり、あるいは、詩集の終わりによって示される。これらの簡略化を適用すると、先ほどの詩集の例を次のように書き換えることができる。
         <anthology>
              <poem><title>The SICK ROSE
              <stanza>
                   <line>O Rose thou art sick.
                   <line>The invisible worm,
                   <line>That flies in the night
                   <line>In the howling storm:
              <stanza>
                   <line>Has found out thy bed
                   <line>Of crimson joy:
                   <line>And his dark secret love
                   <line>Does thy life destroy.

              <poem>
                   <!-- more poems go here    -->

         </anthology>

どの要素を他の要素の中に入れ子にすることができるかを宣言してマークアップを簡略化できることは、SGMLの非常に重要な特徴である。これらの規則について述べる前に、上の例が、コンピュータによって様々な異なる目的に応じて異なる処理をされるとはどういうことなのか知りたいと考えている読者もいることだろう。簡単な索引作成プログラムであれば、関係のあるテクスト要素だけを取り出して、タイトルの一覧、詩の本文中に現れる語彙表を作ることができる。簡単な整形プログラムであれば、スタンザとスタンザの間に空行を挿入することができる。その際、各スタンザの第1行をインデントしたり、スタンザ番号を挿入することも可能である。それぞれの詩の異なる部分ごとに体裁を変えて印刷することもできる。より意欲的で分析的なプログラムであれば、句読点の使い方を、スタンザ上の境界と韻律上の境界を関連づけさせることもできる【注7】。編者が加えたスタンザや行の変更がどのような効果をもたらすかを確かめたければ、研究者はタグの位置を変更するだけでそのようなことが実現できる。そして、もちろん、上に示されたテクストは、あるコンピュータから他のコンピュータへ転送して、埋め込まれたタグの意味を理解することのできるプログラム(あるいは人間)を用いて処理することができる。しかも、ワードプロセッサのファイルであれば必要になる修正や変換を加える必要はない。


2.4 Defining SGML Document Structures: The DTD

前述したような規則は、SGML文書の構造を表わす形式的な仕様、つまり一般にはDTDと略される文書型定義(document type definition)を作成する第一歩である。DTD作成するには、文書デザイナは、状況に応じてDTDの制約を緩めるか強めるかするだろう。単純なルールに従う便利さと、実際のテクストを扱う複雑さの間でバランスを取らなければならない。このことは、特に既存のテクストに使われる規則を定義する場合にあてはまる。デザイナに、古典テクストの元々の目的や意味について非常にぼんやりした理解しかなく、そのため、テクストの構造について一貫したルールを見つけることは難しいと考えることもあるだろう。反対に、例えば、何かのテクストデータベースに入力するために、新しいテクストが厳密な仕様に基づいて用意される場合には、規則が詳細に宣言されればされるほど、規則を当てはめやすくなる。既存のテクストをマークアップする場合であっても、テクストについて一貫した見方や仮説に基づいた制約の強い規則を定義しておくほうがよいだろう。それが、仮にその見方や仮説の有効性を確かめるためであるとしても。ここで注意しなければならないことは、文書型定義とは全てテクストの一つの解釈であるということである。ある特定の分析をするために、あるDTDを他のDTDより優遇することはあるだろうが、テクストについての絶対的な真理のようなものを全て包み込むDTDはありえない。

現在、文書構造の統一性が大きな要件である状況では、SGMLが最も広く使用されている。技術文書の作成では、例えば、セクションやサブセクションが正しく入れ子になり、相互参照が正しく付けられることが非常に重要なことである。そのような状況において、文書は、あらかじめ定義された一連の規則に対応させるべき生の資源であるとみなされる。しかし、既に述べてきたように、単純なルールを使用することで、それほど厳格に制約されていないテクストを正しくタグ付けする手間を簡素化することができる。このような規則を明示的にすることで、学者は電子テクストをマークアップしたり、それを検証する際の重荷を減らすことができる、と、同時に、エンコードされるテクストの構造や有意の特徴についての解釈を明示的に示す必要に迫られることにもなる。

2.4.1 An Example DTD

SGMLにおいて、DTDは、規格で定義された単純な文法を用いた宣言文の集合であると定義される。先ほど取り上げた単純な詩のモデルの場合、次のような宣言が適切だろう。

         <!ELEMENT anthology      - -  (poem+)>
         <!ELEMENT poem           - -  (title?, stanza+)>
         <!ELEMENT title          - O  (#PCDATA) >
         <!ELEMENT stanza         - O  (line+)   >
         <!ELEMENT line           O O  (#PCDATA) >
この5行は、形式的なSGMLの要素宣言である。宣言とは、要素と同じように、左不等号によって区切られる。左不等号に続く文字は感嘆符でなければならず、続いて短いSGMLの定義済みキーワードが来る。上の五つの宣言は、同じ種類である。どれも、ELEMENTというキーワードで始まっており、先に定義された技術的な意味で、それが要素を宣言するものであることを示す。また、どれも、三つの部分から成り立っている。名前、あるいは名前群、最小化規則のための二つの文字、内容モデルである。これらの三つの部分については以下でさらに述べる。宣言の構成素は、ホワイトスペースで、つまり、一つかそれ以上の空白、タブ、改行で区切られる。

上の宣言の一つ目の部分は、宣言される要素の総称識別子を表わす。例えば、poem、titleなどである。以下で述べるが、一つの宣言文で複数の要素を宣言することも可能である。

2.4.2 Minimization Rules

宣言の二つ目の部分は、その要素の最小化規則と呼ばれるものを指定する。この規則は、その要素の出現に際して、開始タグおよび終了タグが存在しなければならないかどうかを決定する。最小化規則は、文字の対になっており、ホワイトスペースによって区切られる。一つ目の文字が、開始タグの、二つ目の文字が終了タグの出現をそれぞれ表わす。どちらの場合も、ハイフンか、"O" の文字("omissible"あるいは"optional"の意)のどちらかが指定されなければならない。ハイフンは、そのタグが存在しなければならないことを示し、文字"O"は、そのタグが省略されてもよいことを示している。そのため、この例では、<line>以外の要素には、開始タグがなければならない。<poem>と<anthology>要素だけは、終了タグも必要である。

2.4.3 Content Model

宣言の、カッコで囲まれた三つ目の部分は、その要素の内容モデルと呼ばれる。それは、その要素中に、どのような要素が正当に出現できるかを指定する。内容は、他の要素か、特別な予約語を使って指定される。予約語にはいくつかあるが、その中でも最も多く出会うものは、この例にあるように、#PCDATAだろう。これは、"parsed character data"(構文解析対象文字データ)の略であり、そのエレメントが、どのような有効文字データを含んでもよいことを定義する。SGMLの宣言を、一人の祖先が頂上に位置する家系図のようなものと考えるなら(ここでの例では、<anthology>が祖先に相当する)、木の枝を下にたどっていけば(例えば、<anthology>から<poem>、<stanza>、<line>、<title>のように)、#PCDATAに行き当たる。この例では、<title>と<line>が、そのように定義されている。その内容モデルは、#PCDATAだけを取り、他の要素の埋め込みについては何も指定していないので、この二つの要素は、他の要素を含むことは出来ない。

2.4.4 Occurance Indicators

<stanza>について、上の例では、一つのスタンザは、一つあるいはそれ以上の行から成り立つと宣言されている。それは出現指示子を使って(それとプラス記号と)、その名前の要素が、その内容モデルの中で、何回出現するかを表わす。SGMLの文法では、三つの出現指定子があり、それぞれ慣例的にに、プラス記号、疑問符、アステリスク(星印)によて表わされる【注8】。プラス記号は、その要素が、1回あるいはそれ以上出現することを意味する。疑問符はその要素が出現するとしても1回で、そうでなければ出現しないということを意味する。星印は、要素が、全く現われないか、1回あるいはそれ以上出現することができるという意味である。そのため、<stanza>の内容モデルが(LINE*)であるとすれば、スタンザには行が全くないということもありうるし、1行以上現われるということもありうる。内容モデルが(LINE?)であるとすれば、スタンザの中身が空と言うこともありうるということを意味するが、どのスタンザも、1行より多くなってはならない。そのため、この例では、<poem>に一つより多くの<title>があってはならないが、全くない分には構わないと宣言されている。そして、最低一つのスタンザがあれば、それ以上いくつスタンザがあっても構わない。

2.4.5 Group Connectors

(title?, stanza+)という内容モデルは、複数の構成素を含んでいる。そのため、さらにそれらの要素がどのような順序で出現するのかを指定する必要がある。この順序は、構成素の間に使われる群接続子(コンマ)によって表わされる。使用可能な群接続子は三つあり、それぞれ慣例的ににコンマ、縦線、アンパサンドによって表わされる【注9】。コンマによって接続される構成素は、必ず内容モデルの順序で現われなければならないことを示す。アンパサンドによって接続される構成素は、二つとも現われなければならないが、どのような順序でもよいことを示す。縦線は結合する構成素のうち一つだけが現われることを示す。この例で、コンマがアンパサンドに置き換えられた場合、タイトルは<poem>中のスタンザの前に来ることも、後に来ることもできる(しかし、スタンザとスタンザの間には来ない)。縦線に置き換えられた場合は、<poem>タイトルかスタンザのどちらかだけで(しかし、両方ではない)成り立つことになる。

2.4.6 Model Groups

これまでの例では、内容モデルのそれぞれの構成素は、一つの要素か、#PCDATAのどちらかであった。しかし、構成素が、群接続子によって接続された要素のリストとなった内容モデルを定義することも可能である。そのようなリストは、モデル群と呼ばれるが、出現指示子によって修飾することもできるし、それ自身を、グループ接続子によって接続することもできる。この機能を説明するために、先ほどから使っている例に、スタンザ型でない韻文を加えることにしよう。説明しやすくするために、ここではスタンザ詩、カプレット詩、ブランクバース詩に分ける。ブランクバース詩は、行だけから成り立つ(ここでは、韻文での段落は無視する【注10】)と考え、それ以上の要素を定義する必要はない。カプレット詩は、<line1>に<line2>が続くものと定義する。

     <!ELEMENT couplet O O (line1, line2) >
要素<line1>と<line2>(例えばこれらは、韻律の研究をするために区別しておくものとする)は、既存の<line>要素と全く同じ内容を持つ。これらは同じ宣言を共有できる。この場合は、名前だけが異なった同じ宣言がいくつも並ぶよりは、名前群を一つの要素宣言の一つ目の構成素としたほうが扱いやすい。名前群は、次のように群接続子によって接続された総称識別子のリストをカッコで囲んだものである。
     <!ELEMENT (line | line1 | line2) O O (#PCDATA) >
要素<poem>の宣言には、こうすると、全部で三通りの変更の可能性が出てくる。
     <!ELEMENT poem - O (title?, (stanza+ | couplet+ | line+) ) >
<poem>は任意のタイトルと、一つかそれ以上のスタンザ、あるいは一つかそれ以上のカプレット、あるいは一つかそれ以上の行が続いたものから成り立つ。この定義と次の定義の違いに注意すること。
     <!ELEMENT poem - O (title?, (stanza | couplet | line)+ ) >
二つ目の例は、出現指示子をグループではなく、グループ内のそれぞれの要素に対して使用して、一つの詩の中に、スタンザ、カプレット、ブランクバースが混在できるようになっている。

このようにして、様々な種類のテクストの構造の複雑さに応じた、非常に複雑な内容モデルを容易に作ることができる。もう一つの例として、折り返し句が出てくるスタンザ詩の場合を考えてみよう。折り返し句(refrain)は、行要素の反復、あるいは詩行に分けられない単なるテクストから構成される。折り返し句は、詩の先頭に現われるか、スタンザの後に任意的に付加される。内容モデルで表現すると、次のようなものになる。

     <!ELEMENT refrain - - (#PCDATA | line+)>
     <!ELEMENT poem    - O (title?,
                           ( (line+)
                           | (refrain?, (stanza, refrain?)+ ) )) >
まとめると、詩を構成するのは、任意のタイトルと、行の連鎖、あるいは任意の折り返し句で始まる群、それに続く、一回以上出現し、構成素としてスタンザと任意の折り返し句を持つ別の群で構成される。折り返し句−スタンザ−スタンザ−折り返し句や、スタンザ−折り返し句−スタンザ−折り返し句のような連鎖は、どちらもこのパタンに従っている。しかし、折り返し句−折り返し句−スタンザ−スタンザや、スタンザ−折り返し句−折り返し句−スタンザ、という連鎖はこのパタンに従っていない。この内容モデルによって明示化される条件の中には、詩が行だけで構成されないのであれば、スタンザが詩の中に一度以上出現しなければならないこと、また、タイトルとスタンザがともに詩の中に存在するのであれば、必ず、タイトル、スタンザの順になっていなければならないこと、がある。

2.5 Complicating the Issue: More on Element Declarations

これまで説明してきた例では、テクスト構造で定義されているそれぞれの要素の直属の構成素が特定できると想定されている。詩はスタンザから成り立ち、詩集は詩から成り立つ。スタンザが詩に属さずに動き回ったり、関係ない他の要素と結びつくことはない。また、詩集が詩の中に含まれることもない。ある文書型の全ての要素は、階層的な構造に配列され、家系図のように一人の祖先が最上位にあり、多くの子ども(多くの場合は#PCDATAを含む要素である)が最下位にある。この全体を通じた単純化が、数々の目的にとって、驚くほど効果的であることが分かるだろう。しかし、実際のテクスト構造の複雑さを記述するためには十分ではない。特に、自由に動き回り、どのような階層にも現われうる要素を記述するには十分でない。また、異なる要素がオーバラップするような、あるいはいくつかの異なる樹形図が同じ文書に認められるような場合にも十分でない。一つ目の問題に対処するために、SGMLでは例外のためのメカニズムを規定している。二つ目の問題のためには、「並行 "concurrent"」文書構造の定義を可能にしている。

2.5.1 Exceptions to the Content Model

ほとんどの文書には、構造のどの階層にも出現できる要素がある。例えば、注釈(note)は、詩全体、あるいは、スタンザ、スタンザの行、行中の一つの単語に対して付けられるだろう。テクスト批評のための版であれば、同じことが種々の異文(variant)について言えるだろう。ここでの単純な例では、内容モデルの一つ一つに任意要素として注釈要素を加えるとしても、それほど厄介というわけではないが、実際の文書はもっと複雑であり、10や20もの階層を含んでいるだろうから、このようなやりかたは難しくなる。

これに対処するため、SGMLでは、例外のリストを作り、内容モデルをさらに修飾できるようになっている。例外のリストには2種類ある。一つは、添加と呼ばれ、モデル群のどの位置でも、あるいは、そのモデルを構成する要素のどれにでも添加することができる。もう一つは、排除と呼ばれ、モデルに含むことのできない要素である。

先ほどの宣言を拡張して、詩のどの位置にでも出現可能だと考える注釈と異文を入れられるようにするためには、次の二つの要素を付け加える必要がある。

     <!ELEMENT (note | variant) - - (#PCDATA)>
要素noteと要素variantは、どの位置にでも現われることができるので、開始タグ、終了タグの両方がなければならない。詩のそれぞれの種類に対して、この二つの要素をつけ加えるのではなく、添加リストという形で、要素poemに付け加えることができる。すると、宣言は次のようになる。
     <!ELEMENT poem - O (title?, (stanza+ | couplet+ | line+) )
                                              +(note | variant) >
(NOTE|VARIANT)の名前リストの前にあるプラス記号は、後続の要素が例外として添加されることを示す。このリストを追加することによって、注釈や異文が、要素poemの内容のどの位置にでも現われることを示す---内容モデルが#PCDATAであると定義された要素の中であっても。これらの要素は、noteやvariant自身の中に現われることもできる。

ここでもし、何かの理由で、noteやvariantがtitle中に現われて欲しくないのであれば、先ほどの<title>の宣言に例外的排除を付け加えることができる。

     <!ELEMENT title  - O  (#PCDATA)  -(note | variant) >
(NOTE|VARIANT)の名前リストの前にあるマイナス記号は、これが例外的排除であることを示す。この宣言を付け加えることで、noteやvariantは、前の例で、の内容モデルに行なった修正から含意されるにも関わらず、タイトル中に現われることができなくなる。

同じように、上の定義を変更して、noteやvariantがそれ自身の中に入れ子になることを防ぐこともできる。

     <!ELEMENT (note | variant) - - (#PCDATA)  -(note | variant) >

注意深い読者であれば、この宣言によって、variantがnote中に、またnoteがvariant中に出現する可能性も排除されることに気づくだろう。例外的添加および排除は、その影響が明白でないため、注意して使わなければならない。

2.5.2 Concurrent Structure

これまで述べてきたのは、全て単純な階層構造であった。つまり、樹形図のどの階層においても、それぞれの節点は、完全にそれより上位の節点に包含される。下に示す図は、これまで述べてきた単純なDTDに従った文書の構造を樹形図として表現したものである(スペースの都合でこのような向きになっている)。これまでに、Blakeの詩が、どのようにして、一つのタイトル、二つの4行スタンザに分けられるかを見てきた。以下の図では、詩集らしくするために、一つのスタンザと一つのタイトルから成る二つ目の詩を付け加えた。

                              |-------------------title
                              |
                              |              |----line1
                              |              |----line2
               |------POEM1---|----stanza1---|----line3
               |              |              |----line4
               |              |
               |              |              |----line5
               |              |----stanza2---|----line6
               |                             |----line7
               |                             |----line8
     anthology-|
               |
               |              |-------------------title
               |              |
               |              |              |----line1
               |              |              |----line2
               |------POEM2---|----stanza1---|----line3
                                             |----line4
                                             |----line5

明らかに、この詩集や他の詩集を記述するための樹形図は他にもたくさんあるだろう。その中には、ここでの樹形図をさらに細かく分割したものもあるだろう。例えば、単語は行をまたがることがないので、行を一つ一つの単語に分けることもあるだろう。しかし同じように明らかなのは、この樹形図にあてはまらないものも多いということである。例えば、韻文の形式的な境界とは合致しない統語構造に興味を持つような場合である。あるいは、もっと単純な例で言えば、版の異なる同じテクストでのページ付けを表現したい場合がある。

これを実現するための一つの方法は、ここでの例で言えば、内容モデルのlineとtitleを一つの群としてページ(page)にまとめることである。そのような要素のための宣言は非常に単純である。

     <!ELEMENT page - - ((title?, line+)+)   >
つまり、一つのページは、一つかそれ以上の無名の群からなり、それぞれの群は、任意のタイトルとそれに続く行の連鎖を含む(このモデルでは、タイトルがページの一番最後に単独で出現できなくなってしまっていることに注意)。しかし、単に要素<page>を既に定義された階層構造に挿入するだけのことが、思ったほど簡単ではないのである。一つのページよりも長い詩や、複数の詩を含むページというものがあるからである。そのために、要素<page>を、<anthology>と<poem>の間に挿入することはできず、<poem>と<stanza>の間に入れることはできない。もちろん、両方の位置に入れることもできない。ここで、最下位に同じ要素(スタンザ、行、タイトル)を持った別の階層構造を作成し、二つの階層構造を、それより上位の構造によって結合できるようになっている必要がある。

文書型定義は、テクストが構造化される階層樹一つ一つについて作成されなければならない。ここまでに築き上げてきた詩集のための定義は、完全な形で示すと次のようなものになる。

         <!DOCTYPE anthology [
         <!ELEMENT anthology      - -  (poem+)             >
         <!ELEMENT poem           - -  (title?, stanza+)   >
         <!ELEMENT stanza         - O  (line+)             >
         <!ELEMENT (title | line) - O  (#PCDATA)           >
         ]>
この例が示すように、文書型の名前は、その文書型の最大の要素、つまり階層中の最上位の要素と同じでなければならない。この宣言に使われている文法については、後述する(2.9.2 "The DTD")。次に、この宣言に並行する文書型のための二つ目の定義を加える。二つ目の文書型は、ページ付き詩集(paged anthology)あるいは、短縮して<p.anth>と呼ぶことにしよう。
         <!DOCTYPE p.anth [
         <!ELEMENT p.anth         - -  (page+)               >
         <!ELEMENT page           - -  ((title?, line+)+)    >
         <!ELEMENT (title|line)   - O  (#PCDATA)             >
         ]>

これで、基となるテクスト---これら二つの文書型定義によって、行やタイトルに分類されるPCDATA構成分---を二通りの視点で見るための定義を行なった。一つ目の視点では、行はスタンザと詩という単位に分類される。そして、もう一つの視点では、ページという単位だけに分類されるのである。どちらの視点であっても、人間の目に見えるのは全く同じテクストであるということに注意すること。二つの階層構造は、同じテクストを二つの異なるやり方で配列しているだけなのである。

二つの視点をマークアップするためには、それぞれの要素がどちらの階層構造に属するのかを示すことが必要である。これは、カッコで囲んだ文書型の名前を、識別子の直前に付加することで示される。また、これは開始タグおよび終了タグの両方に必要である。そのため、ページ(これは、文書型<p.anth>からしか見えない)は、開始タグの位置に<(p.anth)page>、また終了タグの位置に</(p.anth)page>と、タグ付けされなければならない。同じように、要素poemと要素stanzaは文書型<anthology>中にしか現われないので、それぞれ、<(anthology)poem>、<(anthology)stanza>を使ってタグ付けされなければならない。しかし、両方の文書型に現われる要素lineと要素titleについては、文書型の指定をする必要はない。名前だけが与えられたタグは全ての文書型に存在する要素を示すものと想定されることになる。

簡単な例として、Blakeの詩を使って、ページ付けされた詩集で、しかも、第1スタンザの中で改頁される場合を考えてみよう。詩は、次のようにマークアップされる。

         <(anthology)anthology>
         <(p.anth)p.anth>
         <(p.anth)page>

         <!--      other titles and lines on this page here -->

              <(anthology)poem><title>The SICK ROSE
              <(anthology)stanza>
                   <line>O Rose thou art sick.
                   <line>The invisible worm,
         </(p.anth)page>
         <(p.anth)page>
                   <line>That flies in the night
                   <line>In the howling storm:
              <(anthology)stanza>
                   <line>Has found out thy bed
                   <line>Of crimson joy:
                   <line>And his dark secret love
                   <line>Does thy life destroy.
              </(anthology)poem>

         <!--      rest of material on this page here    -->
         </(p.anth)page>

         </(p.anth)p.anth)
         </(anthology)anthology>

これで、タグでは両方の視点が表現されてはいるが、どちらかの視点だけから見た場合の要素だけをテクストから選択することができる。ページ付けだけを処理するプロセッサであれば、P.ANTHと指定されたタグ、あるいは何も指定されていないタグだけを処理する。ANTHOLOGYの視点だけを処理するプロセッサであれば、改頁を無視する。そして、二つの視点を相互に関連づけするプロセッサは、間違うことなく、その処理を行なう。

注意する必要があるのは、CONCURは、SGMLの任意の機能であり、全てのSGMLソフトウェアシステムでそれが使用できるとは限らないということである。また、使用できるとしても、常に規格の文言通りに実装しているというわけでもない。そのため、このガイドラインでは、CONCURを使用する可能性がある場合には、常に、他のやり方も示すことにしている。この問題については、31章 "Multiple Hierarchies" でさらに述べる。

もう一つ注意すべきことは、文書型<anthology>に対応するものがないような新しい要素、例えばページ番号などを文書型<p.anth>に追加することはできないということである。情報を追加する方法の一つについては、次のセクションで述べる。


2.6 Attributes

SGMLの文脈において、属性(attribute)という語は、他の語と同じように、特別な技術的な意味を持つ。属性は、ある意味で、出現する要素を説明するものであるが、内容の一部とは見なされない。例えば、文書中に出現する要素について、その要素の信頼性を表わす属性を付け加えることができる。あるいは、識別のための属性を付け加えて、文書内の別の位置から目的の要素を参照することができる。属性はまさにこのような状況で有用である。

異なる要素が同じ名前の属性を持っていたとしても(例えばTEIの方式では、全ての要素がidという属性を持つと定義されている)、それらは、全て異なるものと見なされ、それぞれ別々の値を割り当てることができる。要素が属性を持つと定義された場合は、属性値は文書実現値の中に出現する要素の開始タグの中で、属性−値という対になって指定される。冗長になるため、終了タグには属性−値の指定をする必要はない。

例えば、次のようなものである。

     <poem id=P1 status="draft"> ... </poem>
要素<poem>は、idとstatusの二つの属性を持つと定義されている。内容が省略されているが、この例の<poem>の実現値では、属性idはP1という値を持ち、属性statusはdraftという値を持つ。SGML処理系は属性の値をどのように扱うこともできる。例えば、整形プログラムは、属性statusがdraftである要素poemと、属性statusがrevisedであるものとで、印刷の体裁を変えることができる。別の処理系は、属性statusの値を、そもそも処理をするかしないかを決定するのに使うかもしれない。属性idは、慣例的にやや特別な使い方をされ、常に一意の値を与えられ、ある要素を識別し、以下で述べるように、相互参照のために使われる。

要素と同じように、属性は、やはり似通った文法を使って、SGMLの文書型定義で宣言される。属性の名前と、その属性を与える要素を指定するとともに、その属性で使用可能な値の種類と、省略時の値を指定することができる。

次の宣言は、先ほど要素<poem>について指定した二つの属性を定義するのに使われる。

     <!ATTLIST poem
               id       ID                              #IMPLIED
               status   (draft | revised | published)   draft        >

属性宣言はATTLISTというシンボルで始まる。これは属性リスト指定が開始するという意味である。この宣言の初めの部分は、属性を与える要素を指定する。ここでの例では、属性は要素<poem>についてのみ宣言されている。いくつかの要素が、同じ属性を共有するなら、全てを一つの宣言文で定義することができる。要素宣言の場合と同じように、いくつかの名前をカッコで囲んで、それらにまとめて属性を与えることができる。属性を与える要素の名前(あるいは名前群)の後に、いくつかの行が続く。宣言される属性一つについて、それぞれ、属性の名前、属性値の種類、省略時値を指定するための三つの部分を持つ行が一つある。

属性名(この例ではidとstatus)は、SGMLにおける他の名前と同じ制約を受ける。属性名はDTD全体を通じて一意である必要はないが、同じ要素に付与される属性の間では一意である必要がある。

要素宣言の二つ目の部分は、上の例で示されたように、二通りの形を取る。一つは、特別なキーワードを使って、属性が取りうる値の種類を定義するもの。上の例では、IDという特別なキーワードを使って、属性IDが要素poemの一つ一つの実現値を識別するための一意の値を与えることを示している(これについては後述)。他のSGMLキーワードには、次のようなものがある。

CDATA
属性値はどのような有効文字データも含むことができ、値の中にタグを含むこともできるが、SGMLパーサにはタグとして認識されず、処理されない
IDREF
属性値は他の要素に対するポインタを含まなければならない(後述のIDについての説明を参照)
NMTOKEN
属性値は名前トークン、つまり(大体において)英数文字であることを示す
NUMBER
属性値は数字だけで構成されることを示す

上の例では、属性statusが取りうる値のリストが与えられている。こうしておくと、パーサは、どの<poem>にも、draft、revised、publishedのどれか一つが属性statusの値として定義されているかどうかを確かめることができる。この方法によらずに、宣言された値がCDATAかNAMEであれば、パーサは属性値としてほとんどどのような文字列も取ることができる(宣言値がNMTOKENであればstatus=awfulあるいはstatus=12345678、CDATAであればstatus="anything goes"あるいはstatus="well, ALMOST anything"など)。もちろん、属性が取りうる値をあらかじめ定義できない場合もあるが、定義できる場合は、ここでの例のように、定義しておいたほうがよい。

属性宣言の三つ目の部分は、属性値が省略された場合にパーサがその属性をどのように解釈するかのための情報である。これを指定するには、以下に上げる特別なキーワードの一つを与えるか、(この例のように)属性値が省略された時に、その属性の値と見なされる値を与える。上の例を使って説明すると、単に<poem>とだけタグ付けされた詩は、パーサによって<poem status=draft>とタグ付けされたのと同じように扱われる。この他には、次のキーワードの一つを使用して属性の省略時値を指定する方法がある。

#REQUIRED
必ず値が指定されなければならない
#IMPLIED
値が指定される必要はない(上の例のID)
#CURRENT
要素中に値が与えられない場合は、最後にその属性に与えられた値が使われる

例えば、先ほどの属性宣言が次のように書き替えられたとしよう。

     <!ATTLIST poem
               id       ID                             #IMPLIED
               status   (draft | revised | published)  #CURRENT      >
その場合、詩集の中で<poem>とだけタグ付けされた詩は、直前の詩と同じstatusを持つものとして扱われる。キーワードが#CURRENTでなく、#REQUIREDであれば、パーサはそのようなタグ付けを、statusの値が指定されていないので誤りであると指摘する。また、draft、revised、published以外の値が与えられた場合も同様に誤りになる。#CURRENTを使用すると、後続の詩には、次にその属性の値が指定されるまで、全て最初に指定された値が使用される。そのため、もし、属性の値が全て同じであるなら、一番初めの値だけが与えられればよい。

あるテクスト要素から他のテクスト要素の出現を参照する必要があることがある。例えば、「注6を参照」あるいは「5章でのべるように」という語句などである。テクストの執筆中には、注や章を表わすための実際の数字は確定していないだろう。記述的マークアップを使用していれば、ページや章の番号は完全に表現上の問題であるので、マークアップされたテクスト中には記入されない。そのような番号は、テクストを処理するプログラムによって割り振られるものである(そして、アプリケーションが異なれば、番号付けも異なることがある)。そのため、SGMLでは、要素の出現に対して、特別な識別子を与えるメカニズムを規定している。それは、同じテクスト中であればどこからでも参照することのできるラベルのようなものである。相互参照は、それ自体がDTDの中で宣言されなければならないある種の要素であると見なされる。どのような場合でも、識別のためのラベルは(名前は恣意的である)、特別な属性の値として与えられる。

例えば、ある詩の注釈の中に他の詩への参照を含みたいと考えたとしよう。まず、それぞれの詩にラベルを振り当てる必要がある。これは、要素<poem>に、先ほどの例のように属性を指定することで行なわれる。

     <!ATTLIST poem
               id       ID     #IMPLIED >

ここで、値がID型でなければならない属性idを定義する。ID型の属性にidという名前を付けなければならないというわけではないのだが、これは広く見られる便利な慣行である。全ての詩が属性idを持たなければならないのではないが、その場合は、パーサが値を与えられていない属性を無視するということに注意すること。参照する予定のある詩に対してだけこの属性を使用すればいいのである。このような詩に対しては、開始タグの中に一意な識別子を与える。次の例を参照。

              <POEM ID=Rose>
                   Text of poem with identifier 'ROSE'
              </POEM>

              <POEM ID=P40>
                   Text of poem with identifier 'P40'
              </POEM>

              <POEM>
                   This poem has no identifier
              </POEM>

次に相互参照のための新しい要素を定義する必要がある。この要素は内容を持たない---これはポインタとしてだけ使われる---しかし、属性を持ち、参照先の要素の識別子を値として取る。この要素は次のような宣言によって実現される。

         <!ELEMENT poemref - O EMPTY                  >
         <!ATTLIST poemref     target IDREF #REQUIRED >

要素<poemref>は内容を持たないので、終了タグは必要ない。この要素はtargetと名付けられた属性を一つだけ持つ。この属性の値は、IDREF型(ここ示している例のような相互参照のためのキーワード)でなければならず、必ず値が与えられなければならない。

これらの宣言を行なっておき、idにRoseという値を与えた詩は、次のようにして参照する。

         Blake's poem on the sick rose <POEMREF TARGET=Rose> ...

SGMLパーサが、この空要素に出会うと、識別子としてROSEを持つ要素が存在するかを確かめる。他のSGML処理系では、どのような処理を追加することもできる。整形プログラムであれば、文書のその位置での正確なページと行数を計算して挿入することもあるだろう。参照先の詩のタイトルと1行目だけ引用することもあるだろう。ハイパテクスト型の処理系であれば、この要素を参照先の詩へのリンクを起動するための印として使用することもあるだろう。SGMLのマークアップの目的は、相互参照が存在することを示すだけであり、それを処理系がどのように扱うかまで決定しているわけではない。


2.7 SGML Entities

ここまで、述べてきたSGMLの特色は、全て文書内の構造要素をマークアップすることに関わっている。SGMLでは、可搬的なやり方で、文書のどのような部分でも、エンコードして名前を付けることのできる単純で柔軟な方法も規定している。SGMLにおいては、実体(entity)という言葉には特別な意味がある。それは、構造上の問題とは関係なく、マークアップされ名前を付けられた文書の一部のことを意味する。実体は、文字列であることも、一つのファイル全体のテクストであることもある。実体を文書中に含むには、実体参照という仕組みを使用する。例えば、

     <!ENTITY tei "Text Encoding Initiative">
この宣言は、teiという名前で、"Text Encoding Initiative"という文字列を値に持つ実体を定義する【注11】。これは内部実体を宣言するための実体宣言の例である。次の宣言はシステム実体を宣言する。
     <!ENTITY ChapTwo SYSTEM "sgmlmkup.txt">
これは、ChapTwoという名前で、システム識別子に関連づけられたテクストを値に持つシステム実体を定義する---この例では、システム識別子はオペレーティングシステム上のファイルの名前であり、実体の置換テクストはそのファイルの内容である。

一度宣言されると、実体は文書中のどの位置からも参照可能である。実体を参照するには、実体の名前の前にアンパサンドを付け、セミコロンを終わりに付ける。実体参照の次が、スペースやレコード終端である場合は、セミコロンを省略できる。

SGMLパーサは、このような実体参照を見つけると、その実体に宣言されている値に即座に置き換える。"The work of the &tei has only just begun" という一節は、"The work of the Text Encoding Initiative has only just begun" と全く同じであるように解釈される。システム実体の場合には、もちろん、オペレーティングシステム上のファイルの内容に置き換わる。"The following text has been suppressed: &ChapTwo;" という一節が展開される時には、ファイルsgmlmkup.txtの内容全てが実体の部分と置き換わる【注12】

実体を使用することで、入力の手間を省くことができ、また、いくつもの文書中で用語の一貫性を維持する手間を省くことができるのは明らかである。ある複雑な文書の印刷をいくつかの印刷所に分けて行なう場合、文書自体には印刷所の名前を入れる必要のあるところを、実体参照によって &site; のように表わすことができる。そうしておいて、それぞれの印刷所で実体宣言を行なえば、文書そのものを変更することなく、印刷所の名前の部分を適切な文字列に置き換えることができる。

このような文字列置換のためのメカニズムには、他にも多くの使い道がある。多くのコンピュータでは図形文字全てを表示できないという悪名高い問題を回避するために使用できる(ましてや、他の文字体系や古典語の場合は言うに及ばずである)。キーボードから直接入力することのできない(あるいは、入力できても通信で正しく送信されない文字)いわゆる「特殊文字」も、実体参照で表現できる。

例えば、初期の印刷テクストで使われた合字をエンコードしたいという場合のことを考えてみよう。cとtの合字は、別字として扱われるものと区別するために、cとtではなく、&ctlig; とエンコードする。leafstopsや罫線なども、テクスト中では覚えやすい実体参照として表現することができる。そのようなテクストを処理する場合、そのようなテクスト要素に対してどのような表現を与えるかは実体宣言によってなされる。例えば、合字が問題にならないのであれば、次のように宣言しておけばよい。

     <!ENTITY ctlig "ct" >
そうすれば、元の文書中にあった区別は消える。もう一方で、合字を表現することのできる整形プログラムが使われるのであれば、実体宣言で、そのようなプログラムが展開後の内容として要求するどのような文字列を与えることができる。

実体宣言のリストは実体集合と呼ばれる。ほとんどのSGML処理系で使用できる標準的な実体の集合が規定されており、実体の名前は、前述したように、SGML規格書やその他の文書の付録として公開されている名前から取られているのが普通である。

実体宣言で与えられる置換値は、もちろん、システムに強く依存している。置換値に使われる文字が直接入力できないものである場合、SGMLではそれを数値によって指定するためのメカニズムを規定している。これを文字参照と呼ぶ。文字参照は、慣例的に &# という文字列で始まり、セミコロンで終わることで、置換文字列中の他の文字と区別される。例えば、使用する整形プログラムが、合字の ct を c と tに加えて、十進値で102で表わされるとすると、実体宣言は次のようなものになる。

     <!ENTITY ctlig "&#102;ct" >
文字参照は、他のハードウェアやソフトウェアに転送された場合、一般的に意味をなさないことがある。このため、文字参照は、一般的には、このような限られた状況でのみ推奨されている。

実体参照のメカニズムは使用する文字集合にない文字を扱う際に便利であるが、ギリシャ語やロシア語での引用を丸ごと実体参照でエンコードすると考えてはならない。そのような場合には、他のメカニズムを使うことが適当である。この点についてはガイドラインの別の所で述べる(4章 "Characters and Character sets")。

実体参照の特別な形であるパラメタ実体は、SGMLマークアップ宣言の内部で使うことができる。パラメタ実体は、前述した実体(技術的には一般実体と呼ばれる)と二つの点で異なる。

パラメタ実体のための宣言は、一般実体のものと同じ形式を取るが、実体宣言のためのキーワードENTITYと実体の名前の間にパーセント記号を挿入する。空白タグとホワイトスペースがパーセント記号の両側にこなければならない。展開後の値が INCLUDE である内部パラメタ実体TEI.prose、値としてファイルmystuff.dtdを参照する内部パラメタ実体TEI.extensions.dtdは、次のように宣言される【注13】
      <!ENTITY % TEI.prose 'INCLUDE'>
      <!ENTITY % TEI.extensions.dtd SYSTEM 'mystuff.dtd'>

TEI文書型定義は、異なるタグ集合の選択を制御し、TEI DTDを修正しやすくするために、パラメタ実体を多用している。この例は3章 "Structure of the TEI Document Type Definition" で挙げる。


2.8 Marked Sections

時として、SGMLパーサに特別な処理をさせるために、テクストのある部分に印を付けられると便利なことがある。例えば、法律文書の決まり文句は、どの州や国において適用されるかで、体系的に取り込むか、削除するかしなければならない("Liability is limited to $50,000"という一文は、デラウェア州では取り込まれる必要があるが、メリーランド州では削除される必要がある)。一連の関連製品の技術的なマニュアルであれば、大半は共通の内容で、異なるのは細部だろう。それなら、一連の全ての製品を一つの文書で記述し、画面表示、あるいは印刷を行なう時点で、ある製品に関係する部分だけ抜き出して維持するほうが便利だろう(だから、車のオイル交換についての記述はほとんどのステップで同じになるだろうが、気化器の記述であれば、エンジンの種類によって異なるだろう)。

SGMLでは、文書作成のそのような実際的な必要に応じるため、マーク指定区域(marked section)という仕組みを規定している。一般的に、先ほどの例から分かるように、この仕組みは、既存のテクストをエンコードする場合より、新たにテクストを作成する場合に有用である。TEIのエンコード方式の利用者のほとんどは、マーク指定区域を使う必要が全くないだろうから、このセクションの以下の記述は読み飛ばしても構わない。しかし、TEI DTDはマーク指定区域を多用しているので、3章 "Structure of the TEI Document Type Definition" の記述を細部まで理解しようと思っているなら、このセクションを熟読し理解すべきである。

SGMLにおけるマーク指定区域のための「特殊な処理」はいくつかの種類に分かれる。それぞれ、次にあげる状況キーワードと関連付けられる。

INCLUDE
マーク指定区域は文書の一部として取り込まれ、通常に処理される。
IGNORE
マーク指定区域は完全に無視される。SGMLアプリケーションプログラムが、出力を作成するのであれば、マーク指定区域は無視され、出力されない。
CDATA
マーク指定区域に、SGMLタグや実体参照と同じ形式の文字列を含むことができるが、これらはSGMLパーサには認識されない(このガイドラインではSGMLのタグ付けの例を引用する時にCDATAマーク指定区域を使用している)。
RCDATA
マーク指定区域に、SGMLタグと同じ形式の文字列を含むことができるが、SGMLパーサには無視される。その一方、実体参照は通常に認識され展開される。
TEMP
マーク指定区域内のテクストは、文書の暫定的な部分である。マーク指定区域は、後から削除や改訂がしやすいよう、主に文書中の位置を示すために使用される。

テクスト中で、マーク指定区域を表わすには、マーク指定区域開始区切り子を前置する。この文字列中には、前述したキーワードのうちの一つ以上が含まれる。マーク指定区域の終わりは、マーク指定区域終了区切り子によって示される。次の例で、2行目と4行目はマーク指定区域の開始と終了を示すものなので無視される。

      In such cases, the bank will reimburse the customer for all losses.
      <![ IGNORE [
      Liability is limited to $50,000.
      ]]>
マーク指定区域のキーワードの中で、TEI DTDを理解するために最も重要なものは、INCLUDEとIGNOREである。これらは、文書、あるいはDTDを部分的に選択して取り込んだり除外するために使われ、DTDを適当な状況に合わせて調整することができる(例えば、処理しようとする文書に適当なDTDの部分を利用者が選択する時に使う)。

しかし、DTDや文書を利用者の必要に応じて調整する際も、INCLUDEやINGOREのキーワードが、そのまま使われることは少ない。(例えば、先ほどの例で、除外された文を取り込むために文書を変更するには、利用者がテクストを編集して、IGNOREをINCLUDEに手動で変更しなければならない。それなら、その文を直接追加、あるいは削除しても同じぐらい簡単であると思われるだろう)。しかし、キーワードは文字通りの形で与えられる必要はなく、パラメタ実体によって表現してもよい。ある文書中に、例えば、メリーランド州でだけ取り込まれればよい文が多いような場合、それぞれの文をマーク指定区域の中に入れ、Marylandという名前のパラメタ実体でキーワードを表現する。そうすると、先ほどの例は次のようなものになる。

      In such cases, the bank will reimburse the customer for all losses.
      <![ %Maryland; [
      Liability is limited to $50,000.
      ]]>
実体MarylandがIGNOREと定義されていれば、キーワードを実体Marylandでマーク付けされたマーク指定区域は処理の際に全て無視される。定義を次のように変更すると、マーク指定区域は文書中に取り込まれる。
      <!ENTITY % Maryland 'INCLUDE'>
DTDのマーク指定区域を制御するために、パラメタ実体をこのように使う場合、外部DTDファイルに通常はデフォルトの宣言が含まれる。利用者がデフォルトの値を上書きしたいのであれば(Marylandのマーク指定区域で行なったように)適切な宣言をDTD部分集合に加えることで、デフォルトの内容を上書きできる【注14】

前のセクションの終わりで示したパラメタ実体宣言の例は、これでより理解できるだろう。

      <!ENTITY % TEI.prose 'INCLUDE'>
      <!ENTITY % TEI.extensions.dtd SYSTEM 'mystuff.dtd'>
という宣言は、DTDの中でproseに関連するとマーク付けされた区域を取り込む効果を持つ。それは外部DTDファイルでは、proseに関連する区域は全てパラメタ実体 TEI.proseで制御されているからである。上の宣言では、TEI.extensions.dtd(この実体の初期値は空文字列である)のデフォルト宣言の内容を上書きして、ファイル mystuff.dtd をDTDの一部として取り込んでいる。

2.9 Putting It All Together

SGMLに適合した文書は、いくつかの部分を持つ。これらの部分全てが、この章で述べられているわけではなく、また、このガイドラインの利用者は知らずにやり過ごすこともできる。しかし、完全さを期すために、以下で、それぞれの部分がどのように相互に関連しているかについて述べるが、有用であることが分かるだろう。

SGML文書は、SGML前書きと文書実現値から構成される。前書きは、SGML宣言部(後述する)と文書型定義を含み、前述したような要素宣言と実体宣言を含んでいる。ソフトウェアシステムによって、文書実現値と前書きを結びつける方法は異なる。例えば、前書きがソフトウェアに組み込まれていて、利用者には見えないようになっている場合もあるだろう。

2.9.1 The SGML Declaration

SGML宣言は、文字集合やSGML区切り子の文字コード、識別子の長さといったSGMLの方言についての基本的な事柄を指定する。TEIに適合した文書型のためのSGML宣言については、39章 "Formal Grammar for the TEI-Interchange-Format Subset of SGML" および、28章 "Conformance"で、さらに述べる。通常、SGML宣言はSGML処理系によってコンパイルされた形で蓄えられているので、利用者には見えない。

2.9.2 The DTD

文書型定義は、文書実現値を検証する際に参照する文書型定義を指定する。SGML宣言のように、文書型定義はSGML処理系によってコンパイルされた形で蓄えられているか、あるいは何らかの形で利用者に見えないようになっていて、文書を検証する前に、文書型の名前だけを指定すればよいようになっている。

最も単純な場合、文書型定義は基本的な文書型定義だけで構成され(一つ以上の並行した文書型定義の可能性もあるだろう)、文書実現値の前に置かれる。

     <!DOCTYPE my.dtd [
         <!-- all declarations for MY.DTD go here -->
         ...
     ]>
     <my.dtd>
         This is an instance of a MY.DTD type document
     </my.dtd>
より一般的には、文書型定義は別のファイルに蓄えられ、次のようにして参照される。
         <!DOCTYPE tei.2 system "tei2.dtd" [
         ]>
         <tei.2>
              This is an instance of an unmodified TEI type document
         </tei.2>
この例では、文書型TEI.2のテクストは明示的に与えられていないが、SGML処理系は引用符中に与えられたシステム識別子で示されるファイルから文書型定義を読み込む。この例のように、何も囲んでいないが角カッコをつけ加えることもできる。

角カッコによって囲まれた部分は、文書型定義部分集合、あるいはDTD部分集合と呼ばれる。これは、次の例のように使い、使用するDTDに対する修正を指定するためのものである。

         <!DOCTYPE tei.2 SYSTEM "tei2.dtd" [
              <!ENTITY tla "Three Letter Acronym">
              <!ELEMENT my.tag - - (#PCDATA)>
              <!-- any other special-purpose declarations or
                   re-definitions go in here -->
         ]>
         <tei.2>
              This is an instance of a modified TEI.2 type document,
              which may contain <my.tag>my special tags</my.tag> and
              references to my usual entities such as &tla;.
         </tei.2>
この例では、文書型定義は、DTD部分集合の内容を読み込み、その後で、キーワードSYSTEMの後に指定されるファイルの内容を読み込む。SGMLでは、一番最初にされた宣言だけが有効であるため、この順序は重要である。上の例では、そのために、DTDの部分集合中の実体tlaの宣言は、ファイルtei2.dtd中の同じ実体の宣言よりも優先される。実体が二度宣言されることはSGML的には全く妥当なことである。このようにして、SGMLのDTDを利用者が修正できるようにしている(反対に、要素は一度しか宣言することができない。<m.tag>の宣言がファイルtei.dtdにも含まれていると、SGMLパーサはエラーを発生する)。TEI文書型定義の結合と拡張の方法は、3章 "Structure of the TEI Document Type Definition" でさらに述べる。

2.9.3 The Document Instance

文書実現値(document instance)とは、文書の内容のことである。文書実現値は、テクスト、マークアップ、一般実体参照だけを含み、新たな宣言を含むことはできない。モジュール化によって、大きな文書を作成するための便利な方法は、DTD部分集合を使用して、文書の個々の断片やモジュールを実体として宣言することである。

         <!DOCTYPE tei.2 [
              <!ENTITY chap1 system "chap1.txt">
              <!ENTITY chap2 system "chap2.txt">
              <!ENTITY chap3 "-- not yet written --">
         ]>
         <tei.2>
         <teiHeader> ... </teiHeader>
         <text>
             <front> ... </front>
             <body>
              &chap1;
              &chap2;
              &chap3;
              ...
         </body>
         </text>
         </tei.2>
この例では、ファイルtei2.dtdに含まれたDTDは、文書の各章を表わすための実体宣言を読み込むように拡張されている。初めの二つは、それぞれの章のテクストが収められているファイルを参照するシステム実体である。三つ目はダミーであり、テクストがまだ存在しないことを示している(空の値になっていてもよい)。文書実現値中の、&chap1; などの実体参照は、パーサによって展開され、要求された値に置き換わる。章ごとのファイル自体は、もちろん、要素、属性リスト、実体宣言のどれも含まない---単なるタグ付きテクストである。

2.10 Using SGML

SGML文書の作成、検証、処理のために様々なソフトウェアがある。ここでは、それらのうち基本的なものについてだけ述べる。もっとも中心となるソフトウェアは、SGMLパーサである。SGMLパーサは、文書型定義を読み込み、文書がそのDTDに従っているかを検証するソフトウェアシステムを生成する。パーサからの出力は、もっとも単純な場合は、単に "Yes" (その文書実現値が有効である)、あるいは "No" (有効でない)となる。しかし、ほとんどのパーサは、正規の形に直された(典型的には、全ての終了タグが付け加えられ、実体参照が置換された)新しい版の文書、あるいは利用者が指定した内容に従って整形された文書実現値を作成するだろう。このようにして得られた出力は、他のソフトウェア(パーサとの結びつくが弱いものも強いものもあるだろうが)で使用し、構造編集、整形、データベース管理といった付加的機能を提供する。

構造編集のためのエディタは高級なワードプロセッサの一種である。これはDTDを処理して得られた情報を使い、利用者が文書を作成している最中に、文書のどの位置でどの要素が要求されているのかを教えてくれる。またこれは、自動的にタグを挿入するなどして、文書を作成する手間を、大いに省いてくれる。

整形プログラムは、タグ付きの文書実現値を処理して、印刷されたものを出力する。例えば、どのフォントを使うか、どのサイズにするかという、印字上の区別の多くは、構造上の区別と密接に関連しており、整形プログラムは、記述的マークアップをこのために利用する。整形プログラムが参照するタグ構造を、SGMLで並行文書構造として定義することも可能である。

テクスト指向型のデータベース管理システムは、典型的には、逆引きファイル索引を使って、文書、あるいは文書の下部単位を指示している。文書中、あるいは文書の下部単位中に出現する語や語のパタンを検索することができる。もちろん、検索する際に有意味の下部単位は、記述的マークアップを使ってマーク付けされた下部単位と深く関わっている。だから、テクストデータベースシステムで、SGMLのタグ付け文書を利用するのは容易なことである。既存の(非テクスト)データベースシステムで、SGMLのマークアップを使って明示化された構造情報が利用できるよう機能を拡張するための研究もなされている。

ハイパテクストシステムは、文書中で、あるいは文書間で連想リンクを使い、テクストを扱うための他の手法を改良している。くり返すが、そのようなシステムを組み立てるのに必要な基本的な部品は、SGMLマークアップにとっても基本的な部品である。個々の文書要素を識別し、リンクする機能は、SGMLの機能の一部である。市販のソフトウェアを使わずに、明示的タグ付けでリンクを表わすことで、ハイパテクストの開発者は、自分が創作したリソースがいつまでも使用可能であることを確信できる。SGML文書をハイパテクストシステムで読めるようにするには、14章 "Linking, Segmentation, and Alignment" で述べられているような、SGMLタグを正しく解釈できる処理系があればよい。

【目次へ戻る】


Notes

注3
International Organization for Standardization, ISO 8879: Information processing--Text and office systems--Standard Generalized Markup Language (SGML), ([Geneva]: ISO, 1986).【戻る】
注4
標準的な「文書体裁記述言語(DSSSL: document style semantics and specification language)」を(SGMLの文法を使って)作成するための作業が進行中である。【戻る】
注5
区切り子に使われている実際の文字(不等号、感嘆符、スラッシュ)を再定義することもできるが、慣例的には、この解説で使われている文字を使用することになっている。【戻る】
注6
この例の出典は、William Blake, Songs of innocence and experience (1794) である。ここで使われているマークアップは解説のためのものであり、TEIに適合したものではない。【戻る】
注7
この単純な例では、文を明示的にマーク付けする際の問題点には言及していない。この問題については、2.5.2 "Concurrent Structures" で述べる。【戻る】
注8
区切り子と同じように、これらも規格によって抽象名が与えられており、適切なSGML宣言を用いて再定義することもできる。【戻る】
注9
ここで「群接続子(group connectors)」と呼ばれているものは、SGMLでは単に「接続詞(connectors)」と呼ばれている。ここでは、接続子がSGMLのモデル群と名前群でのみ使われることを強調するため、「群接続子」という用語を使用している。区切り子や出現指示子と同じように、群接続子にも規格によって抽象名が与えられており、適切なSGML宣言を用いて再定義することもできる。【戻る】
注10
賢明な読者であれば、韻文の段落が行の境界で始まるとは限らず、問題はかなり複雑なものになることに気づいているだろう。2.5.2 "Concurrent Structures" を参照。注11
慣例的に、実体名では、要素名と異なり、大文字と小文字の区別が重要である。【戻る】
注12
厳密に言えば、SGMLはシステム実体がファイルであることを要求するわけではない。システム実体は、原理的にはSGMLパーサが処理できるどのようなデータソース---ファイル、データベース検索の結果、システムファンクションコールの結果---でも構わない。しかし、SGMLを初めて勉強する場合には、システム実体はファイルを参照するものであると考えておくほうが理解しやすいので、ここでは、他のデータ型については触れないことにする。既存のSGML処理系はシステム実体でファイルを参照する機能を実装しているが、他のデータ型をシステム実体で参照できるようになっている処理系は少ない。【戻る】
注13
このような実体宣言は、mystuff.dtd中の宣言で、散文のためのTEI基本タグ集合を拡張する際に使用されるだろう。【戻る】
注14
これは、外部DTDファイル中の宣言に先立って、DTD部分集合中の宣言が読み込まれるためであり、一番先に読み込まれた実体だけが有効となる。この点については、2.7 "SGML Entities" で簡単に述べる。【戻る】

A Gentle Introduction to SGML
かみむらけいすけ訳
掲示者連絡先:古谷俊一
SGMLを考える