要素(モデルグループ)の追加 2/2

2002年10月20日(日)更新


■要素を「モデルグループ単位」で追加

たけち: ここで注意したいのは、まず要素を追加できるのは「モデルグループ単位」であるということだよ。例えば、

    <xsd:complexType name="PoemType">
    <xsd:complexContent>
    <xsd:extension base="PrePoemType">
    <xsd:element ref="yomi" />
    <xsd:element ref="season" />
    </xsd:extension>
    </xsd:complexContent>
    </xsd:complexType>


 というふうに要素の参照を書いて付け加えたくなるけれど、こういう書き方は駄目だよ。

さらら: あ、こんなのは駄目なのね.....(^ ^;

たけち: もう一つ注意したいのは、追加した結果はあくまで、次のようになることだよ。

さらら

拡張(extension)して作られた内容モデルの形式

たけち: たとえば、次の例をみてみよう。

<?xml version="1.0" encoding="Shift_JIS" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="poem" type="PoemType"/>

<xsd:complexType name="PoemType">
<xsd:complexContent>
    <xsd:extension base="PrePoemType">
    <xsd:choice>
    <xsd:element ref="yomi" />
    <xsd:element ref="season" />
    </xsd:choice>
    </xsd:extension>

</xsd:complexContent>
</xsd:complexType>

<xsd:complexType name="PrePoemType">
    <xsd:choice>
    <xsd:element ref="poet" />
    <xsd:element ref="kana" />
    </xsd:choice>
</xsd:complexType>


<xsd:element name="poet" type="xsd:string" />
<xsd:element name="kana" type="xsd:string" />
<xsd:element name="yomi" type="xsd:string" />
<xsd:element name="season" type="xsd:string" />

</xsd:schema>

たけち: 前回の例題との違いはsequenceだったモデルグループが2つともchoiceに変更されていることなんだ。

さらら: あっ、そうなのね。

たけち: この例では、基準型は、PrePoemTypeで
    <xsd:choice>
    <xsd:element ref="poet" />
    <xsd:element ref="kana" />
    </xsd:choice>

なんだね。

さらら: えぇ。

たけち: これに派生型(PoemType)の方で
    <xsd:choice>
    <xsd:element ref="yomi" />
    <xsd:element ref="season" />
    </xsd:choice>

を追加する、ということになるんだけど、一瞬、まるで
    <xsd:choice>
    <xsd:element ref="poet" />
    <xsd:element ref="kana" />

    <xsd:element ref="yomi" />
    <xsd:element ref="season" />

    </xsd:choice>

が結果としてできるような気がするよね。

さらら: え、そうじゃないの?

たけち

たけち: ...(^ ^;) そうじゃなくてぇ、あくまで作られるのは、

拡張(extension)して作られた内容モデルの形式

たけち: なんだから、この場合は、
    <xsd:sequence>
    <xsd:choice>
    <xsd:element ref="poet" />
    <xsd:element ref="kana" />
    </xsd:choice>

    <xsd:choice>
    <xsd:element ref="yomi" />
    <xsd:element ref="season" />
    </xsd:choice>

    <xsd:sequence>
という結果になるんだよ。

さらら: あ、そうかぁ(^^;) でも、何か直感的じゃないわ。それに、これじゃあ、choiceの内容を増やすことができないのよねぇ...

たけち: そうだとも言えるね。ただ、この方法ではchoiceの内容を増やすことができないけれど、オブジェクト指向的にchoiceの内容を増やしたい場合というのは、後で説明する「代替要素」を使うようなケースが少なくないから、実際はそれを使って何とかなる場合もあるよ。これについてはまた後で説明するね。

さらら: ふ〜ん。。。。


■allモデルグループで注意すること

たけち: それから、あと一つ注意しないといけないのは、基準型の内容モデルや、追加したいモデルグループに、allモデルグループは使えない、ということなんだ。

さらら: え、何故なの?

たけち: 以前allについて勉強したとき、
2.allは他のモデルグループに含まれるパーティクルにはなれない。例えば、sequenceの中でallを使うことはできず、必ず複合型定義の中の最外層に存在しなければならない
 ということを説明したよね。ところが基準型の内容モデルにallが使われていると、
    <xsd:sequence>
    <xsd:all>......</xsd:all>
    派生型で付け加えるモデルグループ
    </xsd:sequence>
 という形になるし、派生型で付け加えるモデルグループにallが使われていると、
    <xsd:sequence>
    基準型の内容モデル(モデルグループ)
    <xsd:all>......</xsd:all>
    </xsd:sequence>
 という形になるよね。このどちらも許されない形だよね。ということは、
基準型の内容モデルや、追加したいモデルグループに
allモデルグループは使えない

 ということになるね。

さらら: あら、結局そうなってしまうのね。allって不便だわね。

たけち: 結局、sequence単位での追加になるということは、内容がsequenceばかりのものを後から追加する、という使い方が一番無難に使えるということになるね。

さらら: ふ〜ん、そうなんだ。あら、そう言えば、基準型の後じゃなくて、前に追加するとか、途中に追加するためにはどうしたらいいの?

たけち: うん、それはできない。

さらら: できない!?

たけち: そう、できないんだ。。。(^ ^;) 基準型の前に追加するとか、途中に追加するなんてできないんだよね。

さらら: それってとても不便じゃない?

たけち: ちょっと不便かな(^ ^;

さらら: だいぶ不便だと思うわ。何か今回の話を聞いていたら、「モデルグループの追加」って、すごく使用する際の制約が多い気がするわ。

たけち

たけち: 確かにこのあたりがXML Schemaに対する批判の一つとしてあげられる点だよね。結局「要素の並び」ということをXMLが重視しているのに対し、従来のオブジェクト指向プログラミング言語などは「継承で追加されるデータは順不同の関係」としてしか扱ってこなかった、ということのギャップがここに出ているとも言えるよね。元々順不同の関係である属性については、属性を追加する際にはこのような問題は生じなかった。しかし、データの並び方が問題となる要素では大きな問題になってくるし、XML Schemaを策定するのには、こういったことへの批判からすごく年月を費やしたけれど、結局バランスのとれたこれ以上のうまい解を見つけることができなかったとも言えるね。

さらら: ふ〜ん。

たけち: まあどうしても順不同を使いたいときには、XML Schemaの場合、属性で扱った方がいいかもしれないね。もちろん属性として扱えない複合型データはどうしようもないんだけれども。

さらら: なるほどね。

たけち: それから最後に、前回「名前付きモデルグループ」で解いた、あの要素がたくさんある問題をモデルグループの追加を使って解こうね。UMLのクラス図も載せておくね。

さらら: えっ、えぇ。。。(^ ^;

たけち: 一部にまだ教えていないSubstitution Group(代替グループ)というテクニックを使っているけれど、それはひとまず無視してね(^^;)

たけち

万葉歌のクラス図

※モデルグループの追加を使った万葉歌の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:sequence minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="poem" />
</xsd:sequence>
</xsd:complexType>

<xsd:element name="poem" type="PoemType" abstract="true" />
<xsd:element name="miscellaneousPoem" type="MiscellaneousPoemType" substitutionGroup="poem" />
<xsd:element name="elegy" type="ElegyType" substitutionGroup="poem" />
<xsd:element name="lovePoem" type="LovePoemType" substitutionGroup="poem" />
<xsd:element name="metaphoricalPoem" type="MetaphoricalPoemType" substitutionGroup="poem" />

<xsd:complexType name="PoemType" abstract="true">
<xsd:sequence>
<xsd:element ref="pno" />
<xsd:element ref="date" />
<xsd:element ref="poet" />
<xsd:element ref="yomi" />
<xsd:element ref="situation" minOccurs="0" />
<xsd:element ref="season" minOccurs="0" />
<xsd:element ref="district" minOccurs="0" />
<xsd:element ref="source" minOccurs="0" />
<xsd:element ref="emotion" minOccurs="0" />
</xsd:sequence>
</xsd:complexType>

<xsd:complexType name="MiscellaneousPoemType">
<xsd:complexContent>
<xsd:extension base="PoemType" />
</xsd:complexContent>
</xsd:complexType>

<xsd:complexType name="ElegyType">
<xsd:complexContent>
<xsd:extension base="PoemType">
<xsd:sequence>
<xsd:element ref="on" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>

<xsd:complexType name="LovePoemType">
<xsd:complexContent>
<xsd:extension base="PoemType">
<xsd:sequence>
<xsd:element ref="sendTo" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>

<xsd:complexType name="MetaphoricalPoemType">
<xsd:complexContent>
<xsd:extension base="LovePoemType" />
</xsd:complexContent>
</xsd:complexType>

<xsd:element name="pno" type="xsd:positiveInteger" />
<xsd:element name="date" type="xsd:string" />
<xsd:element name="poet" type="xsd:string" />
<xsd:element name="yomi" type="xsd:string" />
<xsd:element name="situation" type="xsd:string" />
<xsd:element name="season" type="SeasonType" />
<xsd:element name="district" type="xsd:string" />
<xsd:element name="source" type="xsd:string" />
<xsd:element name="emotion" type="xsd:string" />
<xsd:element name="sendTo" type="xsd:string" />
<xsd:element name="on" type="xsd:string" />

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

たけち: 次回は、「複合型内容をもった複合型」の「制限(restriction)」を勉強してみることにするね。

さらら: はい。

次は複合型内容をもった複合型の制限(1)です 。。。。 (^ ^*


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