ENGLISH | JAPANESE |
$Id: step2.sdoc 1.10 2000/11/01 13:41:12 murata Exp $
STEP 2では,同じことを何度も繰り返して記述する代わりに,一回だけ記述しておいたものを繰り返して参照するための機構が加わります.XMLにあるパラメタ実体に相当します.
生け垣モデルを一回だけ記述し,それを繰り返して参照するための機構がhedgeRule
要素です.DTDにあるパラメタ実体のうち,内容モデルで使われるものに相当します.
hedgeRule
要素の構文を次に示します.foo
はパラメタ実体の名前です.
<hedgeRule label="foo"> ...element content model... </hedgeRule>
このように定義したhedgeRule
を参照するには,<hedgeRef label="foo"/>
と書きます.このhedgeRef
要素は,hedgeRule
の中で指定された要素生け垣モデルで置き換えられます.
以下の例では,要素型doc
のためのelementRule
の生け垣モデルからhedgeRule
を参照しています.このelementRule
は,STEP 1の先頭にあるモジュールにあったものを書き換えて,title
以外の部分をhedgeRule
で記述したものです.
<hedgeRule label="doc.body"> <ref label="para" occurs="*"/> </hedgeRule> <elementRule role="doc"> <sequence> <ref label="title"/> <hedgeRef label="doc.body"/> </sequence> </elementRule>
doc.body
への参照は次のように展開されます.
<elementRule role="doc"> <sequence> <ref label="title"/> <ref label="para" occurs="*"/> </sequence> </elementRule>
この例では,elementRule
の中からhedgeRule
を参照しましたが,hedgeRule
の中からも同様に可能です.
hedgeRule
の中には,要素生け垣モデルだけが書けます.データ型参照や混在生け垣モデルは許されません.たとえば,以下の二つはどれも許されません.
<hedgeRule label="mixed.param"> <mixed> <choice occurs="*"> <ref label="em"/> <ref label="strong"/> <choice> </mixed> </hedgeRule> <hedgeRule label="string.param" type="string"/>
hedgeRef
と混在生け垣モデルを併用するときは,hedgeRule
の中でmixed
を使うのではなく,hedgeRef
をmixed
で括ってelementRule
の中に書きます.その例を次に示します.混在生け垣モデルはphrase
を参照しており,phrase
はhedgeRule
で記述されています.
<hedgeRule label="phrase"> <choice> <ref label="em"/> <ref label="strong"/> <choice> </hedgeRule> <elementRule role="p"> <mixed> <hedgeRef label="phrase" occurs="*"/> </mixed> </elementRule>
occurs
属性hedgeRef
要素はoccurs
属性を持つことができますし,hedgeRule
の中に書かれる要素生け垣モデルもoccurs
属性を持つことができます.次の例では,両方にoccurs
属性が指定されています.
<hedgeRule label="bar"> <sequence occurs="+" > <ref label="foo1"/> <ref label="foo2"/> </sequence> </hedgeRule> <elementRule role="foo"> <hedgeRef label="bar" occurs="*"/> </elementRule>
この例をDTDで表現すれば,パラメタ実体の展開がどう行われるべきかは明らかです.
<!ENTITY % bar "(foo1, foo2)+"> <!-- original --> <!ELEMENT foo (%bar;)*> <!-- expanded --> <!ELEMENT foo ((foo1, foo2)+)*>
上の例を展開した結果を次に示します.展開のときに,一つしか子供を持たないchoice
要素が導入されていることに注意して下さい.これは,hedgeRef
要素にあったoccurs="*"
を引き継いでいます.
<elementRule role="foo"> <choice occurs="*"> <sequence occurs="+" > <ref label="foo1"/> <ref label="foo2"/> </sequence> </choice> </elementRule>
hedgeRef
とhedgeRule
の
順番DTDにあるパラメタ実体と違い,hedgeRef
で参照する前にhedgeRule
を書く必要はありません.たとえば,次の記述はエラーではありません.
<elementRule role="doc"> <sequence> <ref label="title"/> <hedgeRef label="doc.body"/> </sequence> </elementRule> <hedgeRule label="doc.body"> <ref label="para" occurs="*"/> </hedgeRule>
自分自身を直接または間接に参照するようなhedgeRule
を書いてはいけません.次の例では,bar
のための生け垣モデルの中でbar
を参照していますからエラーになります.
<hedgeRule label="bar"> <choice> <ref label="title"/> <hedgeRef label="bar" occurs="*"/> </choice> </hedgeRule>
次の例では,bar1
のための生け垣モデルの中でbar2
を参照しており,bar2
のための生け垣モデルの中でbar1
を参照しています.したがって,エラーになります.
<hedgeRule label="bar1"> <hedgeRef label="bar2" occurs="*"/> </hedgeRule> <hedgeRule label="bar2"> <choice> <ref label="title"/> <hedgeRef label="bar1"/> </choice> </hedgeRule>
empty
の用途STEP 1で述べたempty
は,主にhedgeRule
の中で使います.以下に例を示します.
<hedgeRule label="frontMatter"> <empty/> </hedgeRule> <elementRule role="section"> <sequence> <ref label="title"/> <hedgeRef label="frontMatter"/> <ref label="para" occurs="*"/> </sequence> </elementRule>
このモジュールを再利用する人は,frontMatter
の記述をカスタマイズすることによって,section
の構造を変更できます.
同じくSTEP 1で述べたnone
もhedgeRule
の中で使います.以下に,使用例を示します.
<hedgeRule label="local-block-class"> <none/> </hedgeRule> <hedgeRule label="block-class"> <choice> <ref label="para"/> <ref label="fig"/> <hedgeRef label="local-black-class"/> </choice> </hedgeRule>
このモジュールを再利用する人は,local-block-class
の記述をカスタマイズすることによって,block-class
の内容を変更できます.
属性宣言をいくつかまとめて一回だけ記述し,それを繰り返して参照するための機構がattPool要素です.DTDにあるパラメタ実体のうち,属性リスト宣言で使われるものに相当します.
attPool
要素の構文を下に示します.foo
はパラメタ実体の名前です.
<attPool role="foo"> ...attribute definitions... </attPool>
このように定義したattPool
を参照するには,属性定義の並びの先頭に<ref role="foo"/>
と書きます.このref
要素は,attPool
の中で指定された属性定義の並びで置き換えられます.
以下の例では,要素型title
のためのtag
要素からattPool
を参照しています.このtag
は,STEP 1の先頭にあるモジュールにあったものを書き直したものです.多くの要素型に共通するrole
属性が,common.att
というattPool
に記述されています.
<attPool role="common.att"> <attribute name="class" type="NMTOKEN"/> </attPool> <tag name="title"> <ref role="common.att"/> <attribute name="number" required="true" type="integer"/> </tag>
ref
要素は次のように展開されます.
<tag name="title"> <attribute name="class" type="NMTOKEN"/> <attribute name="number" required="true" type="integer"/> </tag>
この例では,tag
の中からattPool
を参照しましたが,attPool
の中からも同様に可能です.
ref
とattPool
の順番ref
で参照する前にattPool
を書く必要はありません.たとえば,次の記述はエラーではありません.
<tag name="title"> <ref role="common.att"/> <attribute name="number" required="true" type="integer"/> </tag> <attPool role="common.att"> <attribute name="role" type="NMTOKEN"/> </attPool>
一つのtag
またはattPool
の中に,複数のref
要素を書くことができます.以下に,一つのattPool
のなかで複数のref
要素を用いた例を示します.必須の属性をcommon-req.att
にまとめ,必須ではない属性をcommon-opt.att
にまとめています.この二つをcommon.att
を記述するattPool
から参照しています.
<attPool role="common.att"> <ref role="common-req.att"/> <ref role="common-opt.att"/> </attPool> <attPool role="common-req.att"> <attribute name="role" type="NMTOKEN" required="true"/> </attPool> <attPool role="common-opt.att"> <attribute name="id" type="NMTOKEN"/> </attPool>
hedgeRule
のときと同様に,自分自身を直接的または間接的に参照するのはエラーです.たとえば,次の例はエラーです.
<attPool role="bar1"> <ref role="bar2"/> <attribute name="id" type="NMTOKEN"/> </attPool> <attPool role="bar2"> <ref role="bar1"/> </attPool>
STEP 2までで,XMLのDTDで出来ることはだいたい出来ます.ぜひ使ってみて下さい.RELAX!