属性宣言: 名前付き属性グループ定義-2

2002年9月8日(日)更新


■万葉歌データのDTD

たけち: どう? 少し考えてみた?

さらら: えっ、えぇ。。。こんな感じなのかしら・・・・・(^ ^; でもずいぶんと長ったらしくなっちゃったわ。

さらら

■さららの考えたDTD
<!ELEMENT poems (miscellaneousPoem | elegy | lovePoem | metaphoricalPoem)*>
<!ELEMENT miscellaneousPoem (#PCDATA)>
<!ELEMENT elegy (#PCDATA)>
<!ELEMENT lovePoem (#PCDATA)>
<!ELEMENT metaphoricalPoem (#PCDATA)>

<!ATTLIST miscellaneousPoem pno NMTOKEN #REQUIRED>
<!ATTLIST miscellaneousPoem date CDATA #REQUIRED>
<!ATTLIST miscellaneousPoem poet CDATA #REQUIRED>
<!ATTLIST miscellaneousPoem situation CDATA #IMPLIED>
<!ATTLIST miscellaneousPoem season (春 | 夏 | 秋 | 冬) #IMPLIED>
<!ATTLIST miscellaneousPoem district CDATA #IMPLIED>
<!ATTLIST miscellaneousPoem source CDATA #IMPLIED>
<!ATTLIST miscellaneousPoem emotion CDATA #IMPLIED>

<!ATTLIST elegy pno NMTOKEN #REQUIRED>
<!ATTLIST elegy date CDATA #REQUIRED>
<!ATTLIST elegy poet CDATA #REQUIRED>
<!ATTLIST elegy situation CDATA #IMPLIED>
<!ATTLIST elegy season (春 | 夏 | 秋 | 冬) #IMPLIED>
<!ATTLIST elegy district CDATA #IMPLIED>
<!ATTLIST elegy source CDATA #IMPLIED>
<!ATTLIST elegy emotion CDATA "追悼">
<!ATTLIST elegy on CDATA #REQUIRED>

<!ATTLIST lovePoem pno NMTOKEN #REQUIRED>
<!ATTLIST lovePoem date CDATA #REQUIRED>
<!ATTLIST lovePoem poet CDATA #REQUIRED>
<!ATTLIST lovePoem situation CDATA #IMPLIED>
<!ATTLIST lovePoem season (春 | 夏 | 秋 | 冬) #IMPLIED>
<!ATTLIST lovePoem district CDATA #IMPLIED>
<!ATTLIST lovePoem source CDATA #IMPLIED>

<!ATTLIST lovePoem emotion CDATA "恋愛">
<!ATTLIST lovePoem sendTo CDATA #REQUIRED>

<!ATTLIST metaphoricalPoem pno NMTOKEN #REQUIRED>
<!ATTLIST metaphoricalPoem date CDATA #REQUIRED>
<!ATTLIST metaphoricalPoem poet CDATA #REQUIRED>
<!ATTLIST metaphoricalPoem situation CDATA #IMPLIED>
<!ATTLIST metaphoricalPoem season (春 | 夏 | 秋 | 冬) #IMPLIED>
<!ATTLIST metaphoricalPoem district CDATA #IMPLIED>
<!ATTLIST metaphoricalPoem source CDATA #IMPLIED>

<!ATTLIST metaphoricalPoem emotion CDATA "恋愛">
<!ATTLIST metaphoricalPoem sendTo CDATA #REQUIRED>

たけち: こうしてみると、すごい行数のDTDになってしまったね。

さらら: そうなのよねぇ〜。同じ内容の属性宣言が多いのよね。

たけち: そうだね。それじゃあ、この属性宣言をちょっとすっきりさせることを考えていこうね。まず、これはこんな書き方に直せるんだ。

たけち

■属性宣言の書き方を変えてみました
<!ELEMENT poems (miscellaneousPoem | elegy | lovePoem | metaphoricalPoem)*>
<!ELEMENT miscellaneousPoem (#PCDATA)>
<!ELEMENT elegy (#PCDATA)>
<!ELEMENT lovePoem (#PCDATA)>
<!ELEMENT metaphoricalPoem (#PCDATA)>

<!ATTLIST miscellaneousPoem pno NMTOKEN #REQUIRED
        date CDATA #REQUIRED
        poet CDATA #REQUIRED
        situation CDATA #IMPLIED
        season (春 | 夏 | 秋 | 冬) #IMPLIED
        district CDATA #IMPLIED
        source CDATA #IMPLIED>

<!ATTLIST miscellaneousPoem emotion CDATA #IMPLIED>

<!ATTLIST elegy pno NMTOKEN #REQUIRED
        date CDATA #REQUIRED
        poet CDATA #REQUIRED
        situation CDATA #IMPLIED
        season (春 | 夏 | 秋 | 冬) #IMPLIED
        district CDATA #IMPLIED
        source CDATA #IMPLIED>

<!ATTLIST elegy emotion CDATA "追悼">
<!ATTLIST elegy on CDATA #REQUIRED>

<!ATTLIST lovePoem pno NMTOKEN #REQUIRED
        date CDATA #REQUIRED
        poet CDATA #REQUIRED
        situation CDATA #IMPLIED
        season (春 | 夏 | 秋 | 冬) #IMPLIED
        district CDATA #IMPLIED
        source CDATA #IMPLIED>

<!ATTLIST lovePoem emotion CDATA "恋愛">
<!ATTLIST lovePoem sendTo CDATA #REQUIRED>

<!ATTLIST metaphoricalPoem pno NMTOKEN #REQUIRED
        date CDATA #REQUIRED
        poet CDATA #REQUIRED
        situation CDATA #IMPLIED
        season (春 | 夏 | 秋 | 冬) #IMPLIED
        district CDATA #IMPLIED
        source CDATA #IMPLIED>

<!ATTLIST metaphoricalPoem emotion CDATA "恋愛">
<!ATTLIST metaphoricalPoem sendTo CDATA #REQUIRED>

さらら: あっ、そっか〜。こんな書き方ができたのね。。。。でも、ほんのちょっと短くなっただけだわ。

たけち: このままではそうだね。これをさらにこう書き直してみるよ。

■パラメータエンティティを使ってさらに短く
<!ELEMENT poems (miscellaneousPoem | elegy | lovePoem | metaphoricalPoem)*>
<!ELEMENT miscellaneousPoem (#PCDATA)>
<!ELEMENT elegy (#PCDATA)>
<!ELEMENT lovePoem (#PCDATA)>
<!ELEMENT metaphoricalPoem (#PCDATA)>

<!ENTITY % poem_common "pno NMTOKEN #REQUIRED
        date CDATA #REQUIRED
        poet CDATA #REQUIRED
        situation CDATA #IMPLIED
        season (春 | 夏 | 秋 | 冬) #IMPLIED
        district CDATA #IMPLIED
        source CDATA #IMPLIED">


<!ATTLIST miscellaneousPoem %poem_common;>
<!ATTLIST miscellaneousPoem emotion CDATA #IMPLIED>

<!ATTLIST elegy %poem_common;>
<!ATTLIST elegy emotion CDATA "追悼">
<!ATTLIST elegy on CDATA #REQUIRED>

<!ATTLIST lovePoem %poem_common;>
<!ATTLIST lovePoem emotion CDATA "恋愛">
<!ATTLIST lovePoem sendTo CDATA #REQUIRED>

<!ATTLIST metaphoricalPoem %poem_common;>
<!ATTLIST metaphoricalPoem emotion CDATA "恋愛">
<!ATTLIST metaphoricalPoem sendTo CDATA #REQUIRED>


■パラメータエンティティ

さらら: へぇ〜、こんな書き方ができるの! すっきりしているわね。

たけち: そうだね。DTDで使ったこの技をパラメータエンティティと言うんだよ。以前外部エンティティを勉強したけれど、それにちょっと似ているね。パラメータエンティティもエンティティの一種なんだけど、これはXML文書内で使われるエンティティではなくて、DTDの中だけで使われるエンティティなんだよ。この場合、共通の属性については、poem_common というパラメータエンティティを定義し、それをDTDの属性宣言の中で、%poem_common;と書くことによって参照しているんだ。それによって、共通の属性を属性宣言したことと同じ意味になるんだよ。

さらら: ふぅ〜ん。そうなんだぁ。

たけち: さて、ここまではDTDの話だったけれど、今度はXML Schemaに話を戻そうね。まずさっきのDTDと同じ意味のXML Schemaを書いてみようか。もうだいたい書けるよね。

さらら: え゛っ。。。(? ?;

たけち: じゃぁ、つぎのりストを見て。

たけち


■XML Schemaによる万葉歌スキーマ

■万葉歌データをXML Schemaで定義
<?xml version="1.0" encoding="shift_JIS" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="poems" type="PoemsType" />

<xsd:complexType name="PoemsType">
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="miscellaneousPoem" />
<xsd:element ref="elegy" />
<xsd:element ref="lovePoem" />
<xsd:element ref="metaphoricalPoem" />
</xsd:choice>

</xsd:complexType>

<xsd:element name="miscellaneousPoem" type="MiscellaneousPoemType" />
<xsd:element name="elegy" type="ElegyType" />
<xsd:element name="lovePoem" type="LovePoemType" />
<xsd:element name="metaphoricalPoem" type="MetaphoricalPoemType" />

<xsd:complexType name="MiscellaneousPoemType">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="pno" type="xsd:NMTOKEN" use="required"/>
<xsd:attribute name="date" type="xsd:string" use="required"/>
<xsd:attribute name="poet" type="xsd:string" use="required"/>
<xsd:attribute name="situation" type="xsd:string" use="optional"/>
<xsd:attribute name="season" type="SeasonType" use="optional"/>
<xsd:attribute name="district" type="xsd:string" use="optional"/>
<xsd:attribute name="source" type="xsd:string" use="optional"/>

<xsd:attribute name="emotion" type="xsd:string" use="optional"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>

<xsd:complexType name="ElegyType">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="pno" type="xsd:NMTOKEN" use="required"/>
<xsd:attribute name="date" type="xsd:string" use="required"/>
<xsd:attribute name="poet" type="xsd:string" use="required"/>
<xsd:attribute name="situation" type="xsd:string" use="optional"/>
<xsd:attribute name="season" type="SeasonType" use="optional"/>
<xsd:attribute name="district" type="xsd:string" use="optional"/>
<xsd:attribute name="source" type="xsd:string" use="optional"/>
<xsd:attribute name="emotion" type="xsd:string" default="追悼"/>
<xsd:attribute name="on" type="xsd:string" use="required"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>

<xsd:complexType name="LovePoemType">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="pno" type="xsd:NMTOKEN" use="required"/>
<xsd:attribute name="date" type="xsd:string" use="required"/>
<xsd:attribute name="poet" type="xsd:string" use="required"/>
<xsd:attribute name="situation" type="xsd:string" use="optional"/>
<xsd:attribute name="season" type="SeasonType" use="optional"/>
<xsd:attribute name="district" type="xsd:string" use="optional"/>
<xsd:attribute name="source" type="xsd:string" use="optional"/>

<xsd:attribute name="emotion" type="xsd:string" default="恋愛"/>
<xsd:attribute name="sendTo" type="xsd:string" use="required"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>

<xsd:complexType name="MetaphoricalPoemType">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="pno" type="xsd:NMTOKEN" use="required"/>
<xsd:attribute name="date" type="xsd:string" use="required"/>
<xsd:attribute name="poet" type="xsd:string" use="required"/>
<xsd:attribute name="situation" type="xsd:string" use="optional"/>
<xsd:attribute name="season" type="SeasonType" use="optional"/>
<xsd:attribute name="district" type="xsd:string" use="optional"/>
<xsd:attribute name="source" type="xsd:string" use="optional"/>

<xsd:attribute name="emotion" type="xsd:string" default="恋愛"/>
<xsd:attribute name="sendTo" type="xsd:string" use="required"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>

<xsd:simpleType name="SeasonType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="春" />
<xsd:enumeration value="夏" />
<xsd:enumeration value="秋" />
<xsd:enumeration value="冬" />
</xsd:restriction>
</xsd:simpleType>

</xsd:schema>

さらら: わぁ〜。。。長いわねぇ〜。。それに、<xsd:choice minOccurs="0" maxOccurs="unbounded">ってなあに??

たけち: あっ、それは無視してね (^ ^;
一応、DTDの
<!ELEMENT poems (miscellaneousPoem | elegy | lovePoem | metaphoricalPoem)*>
に相当するのが、
<xsd:complexType name="PoemsType">
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="miscellaneousPoem" />
<xsd:element ref="elegy" />
<xsd:element ref="lovePoem" />
<xsd:element ref="metaphoricalPoem" />
</xsd:choice>

</xsd:complexType>
なんだけど。。。まだ <xsd:choice> は勉強していないから、ここはとばしてね (^ ^; 見てもらいたいのは、属性の宣言のところだから。

さらら: これも同じような宣言がいっぱい出てきて大変だわ。

たけち: そうだね。これとさっきのDTDのパラメータエンティティを比べてみてどう思うかい?

さらら: XML SchemaにもDTDのパラメータエンティティと同じ機能が欲しいわね。

たけち: そうだよね。そこで登場するのが 名前付き属性グループ定義というテクニックなんだよ。

たけち


■XML Schemaの名前付き属性グループ定義

■名前付き属性グループ定義を使用
<?xml version="1.0" encoding="Shif_JIS" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="poems" type="PoemsType" />

<xsd:complexType name="PoemsType">
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="miscellaneousPoem" />
<xsd:element ref="elegy" />
<xsd:element ref="lovePoem" />
<xsd:element ref="metaphoricalPoem" />
</xsd:choice>
</xsd:complexType>

<xsd:element name="miscellaneousPoem" type="MiscellaneousPoemType" />
<xsd:element name="elegy" type="ElegyType" />
<xsd:element name="lovePoem" type="LovePoemType" />
<xsd:element name="metaphoricalPoem" type="MetaphoricalPoemType" />

<xsd:attributeGroup name="poem_common">
<xsd:attribute name="pno" type="xsd:NMTOKEN" use="required"/>
<xsd:attribute name="date" type="xsd:string" use="required"/>
<xsd:attribute name="poet" type="xsd:string" use="required"/>
<xsd:attribute name="situation" type="xsd:string" use="optional"/>
<xsd:attribute name="season" type="SeasonType" use="optional"/>
<xsd:attribute name="district" type="xsd:string" use="optional"/>
<xsd:attribute name="source" type="xsd:string" use="optional"/>
</xsd:attributeGroup>


<xsd:complexType name="MiscellaneousPoemType">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attributeGroup ref="poem_common" />
<xsd:attribute name="emotion" type="xsd:string" use="optional"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>

<xsd:complexType name="ElegyType">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attributeGroup ref="poem_common" />
<xsd:attribute name="emotion" type="xsd:string" default="追悼"/>
<xsd:attribute name="on" type="xsd:string" use="required"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>

<xsd:complexType name="LovePoemType">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attributeGroup ref="poem_common" />
<xsd:attribute name="emotion" type="xsd:string" default="恋愛"/>
<xsd:attribute name="sendTo" type="xsd:string" use="required"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>

<xsd:complexType name="MetaphoricalPoemType">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attributeGroup ref="poem_common" />
<xsd:attribute name="emotion" type="xsd:string" default="恋愛"/>
<xsd:attribute name="sendTo" type="xsd:string" use="required"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>

<xsd:simpleType name="SeasonType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="春" />
<xsd:enumeration value="夏" />
<xsd:enumeration value="秋" />
<xsd:enumeration value="冬" />
</xsd:restriction>
</xsd:simpleType>


</xsd:schema>

さらら: なるほど、名前付き属性グループ定義って便利なのね。さっきのDTDのパラメータエンティティと似たような流れで定義できているわ。

たけち: そうだね。ちょうどDTDのパラメータエンティティを属性宣言に適用したのと同じ効果をもっているのが 名前付き属性グループ定義 なんだ。ちなみに、DTDのパラメータエンティティは属性宣言だけでなくて、要素宣言の部分に対しても適用できるんだ。これに相当するXML Schemaの機能を 名前付きモデルグループ定義 というんだけど...

さらら: ・・・・・(? ?;

たけち: あっ、それはもっと先に勉強することにするね (^ ^;

さらら: それにしても、これだけたくさんの共通する属性を扱うって、本当に大変だわね。(.....あぁ、良かった (^ ^; )

たけち: そうだね。でも、これと同じ結果をまた別の観点から得ることができる、もっとスマートな方法もXML Schemaにはあって...

さらら: えっ?

その話は次回の属性の追加にて 。。。。 (^ ^)v

さらら


XMLスキーマのコーナーは、TAKABEさま(XSLTの遊び部屋)の全面的なご協力をいただいて作成しています。