複合型内容を持つ複合型の定義の基本-2/2

2002年9月29日(日)更新


■基準型は書かなくちゃいけないの?

さらら: 制限された結果どうなるかということを書くぐらいだったら、基準型を書く意味がないんじゃないの? 派生を使う意味があるのかしら?

たけち: やっぱり。。。さららでもそう思った? (^ ^;

さらら: 誰だってそう思うんじゃないかしら。制約ファセットのように、基準型をどう制限するか、ということなら理解できるわ。でも制限した結果どうなるか、ということが書かれているのなら、基準型が何でも関係ないように思えるわ。結局この制限で意味があるのは、属性のところだけじゃない。例えばさっきの、PoemTypeだと、基準型をPrePoemTypeからxsd:anyTypeに変えても、属性のところだけ付け加えれば意味が全然変わらないんじゃないの?

たけち

■PrePoemTypeを使わないでPoemTypeを定義
<?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:restriction base="xsd:anyType">
    <xsd:sequence>
    <xsd:element ref="kana" />
    <xsd:element ref="yomi" />
    </xsd:sequence>

    <xsd:attribute name="pno" type="xsd:positiveInteger"/>
    </xsd:restriction>
</xsd:complexContent>
</xsd:complexType>

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

</xsd:schema>


■xsd:anyTypeを基準型としたときの省略形式

たけち: 確かにこの定義に従う要素の構造だけを見ればそういうことになるね。DTDで言えば、どちらも
    <!ELEMENT poem (kana, yomi)>
    <!ATTLIST poem pno CDATA #REQUIRED>
    <!ELEMENT kana (#PCDATA)>
    <!ELEMENT yomi (#PCDATA)>
という意味で変わらないよね。

さらら: それに、前のページの例で、ただ単に空要素の複合型をあらわすだけで、こんなに行数を書かないといけないわけなの? 基準型が何でも、内容モデルのところに何も書かなければ、それは空(empty)を意味している、ということは、その空(empty)を包む部分で無駄なことを書いて、いたずらに行数を増やしているような気がするわ。

たけち: うん。確かに、さららの言うとおり、こういう書き方は無意味に冗長なように見えるよね。そこでXML Schemaでは、複合型の内容でxsd:anyTypeを基準型として制限する場合に限り、次の2つの開始タグ
    <xsd:complexContent>
    <xsd:restriction base="xsd:anyType">
と、それに対応する終了タグ
    </xsd:restriction>
    </xsd:complexContent>
まとめて省略しても良い、ということにしてあるんだよ。

さらら: えっ。。

さらら

たけち

たけち: 逆に考えると、<xsd:complexType>の内容が、
<xsd:complexContent>でも<xsd:simpleContent>でもなく、
突然、<xsd:sequence>などのモデルグループから始まっている場合は、

    <xsd:complexContent>
    <xsd:restriction base="xsd:anyType">
        :
        :
    </xsd:restriction>
    </xsd:complexContent>

が省略されている状態だと解釈することになっているんだよ。だから一番最初の例は以下のように書き直すことができるんだよ。

xsd:anyTypeを基準型としたときに省略できる要素記述

■xsd:anyTypeを基準型とした複合型のスキーマ(省略形式)
<?xml version="1.0" encoding="Shift_JIS" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

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

<xsd:complexType name="PrePoemType">
    <xsd:sequence>
    <xsd:element ref="poet" minOccurs="0" />
    <xsd:element ref="kana" />
    <xsd:element ref="yomi" />
    </xsd:sequence>

    <xsd:attribute name="pno" type="xsd:positiveInteger" use="required" />
</xsd:complexType>

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

</xsd:schema>

さらら: これならずいぶんすっきりした感じだわ。 (^ ^*

たけち: じゃあ、さららが気にしていた空要素のデータ型は、この省略形を使うと、complexType要素の中身が消えてしまって次のようになるんだよ。

さらら

■空要素のスキーマ(省略形)
<?xml version="1.0" encoding="Shift_JIS" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="kara" type="KaraType" />

<xsd:complexType name="KaraType" />

</xsd:schema>


■空要素のスキーマの書き方

さらら: うんうん。。。

たけち: 実際問題、この省略形を使って書いた方がすっきりしているよね。ついでに内容が無くて属性だけ有る要素の書き方も知っておこうね。例えば

    <poem pno="8" />

にあたるスキーマを考えてみようね。DTDでは

    <!ELEMENT poem EMPTY>
    <!ATTLIST poem pno CDATA #REQUIRED>

にあたるものだよ。

■xsd:anyTypeを基準型とした複合型のスキーマ(省略しない形式)
<?xml version="1.0" encoding="Shift_JIS" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

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

<xsd:complexType name="PrePoemType">
<xsd:complexContent>
    <xsd:restriction base="xsd:anyType">
    <xsd:attribute name="pno" type="xsd:positiveInteger" use="required" />
    </xsd:restriction>
</xsd:complexContent>
</xsd:complexType>

</xsd:schema>

たけち: このスキーマを省略形を使うとつぎのように書けるんだよ。

■xsd:anyTypeを基準型とした複合型のスキーマ(省略形式)
<?xml version="1.0" encoding="Shift_JIS" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

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

<xsd:complexType name="PrePoemType">
    <xsd:attribute name="pno" type="xsd:positiveInteger" use="required" />
</xsd:complexType>

</xsd:schema>


■XML Schemaでは派生が原則

さらら: へ〜っ、省略できるんだ〜。確かにこう書くと、派生しているようには見えないけれど、でも本当はxsd:anyTypeが基準型になって派生していることが省略されているのね。。。。それにしても、何かずるい感じがするわ。

たけち: まあ、確かにそうだね(^^;) XML Schemaでは、

自分でXMLスキーマのデータ型を定義したければ、必ず他の何らかのデータ型を基準型として、そこから派生させるという形をとらない限り、自分でデータ型を定義することはできない

という基本原則があるということを前に話をしたよね。
でも、その基本原則を守る意味がない、それどころか基本原則を守っていると、やたらと面倒になる場合が、このようにあるんだ。そこで省略形を認めて、実質的に無意味に近い冗長な記述の大部分を書かずにすむようになっているわけなんだよね。まあ基本原則を建前として堅持しつつ、実質的にはそれを無視する形で簡略化したというところかな。

さらら: 何か、私たちの時代でもあった、世の中の複雑な側面を、コンピュータの世界でも見た感じよね。だからComplexTypeなのかしら。。。。 (^ ^;
それにしても、こんなことをしてまで「派生」の基本原則にこだわりたいわけなの?

たけち: そう、ここまでして「派生」、つまりオブジェクト指向における「継承」の概念を導入しているのが、良くも悪くもXML Schemaの大きな特徴なんだ。そしてこういった特徴がXML Schemaの長所であると同時に、大きな非難を浴びる原因になっていると思うんだ。


■オブジェクト指向モデルとXMLスキーマ

たけち: 以前も説明したように、欧米のソフトウェア業界ではもうオブジェクト指向モデリングは常識化して中心的なスタンダードな手法となっている。そういうオブジェクト指向モデリングを中心に使っているところでは、直接、オブジェクト指向モデルからスキーマが書けるというのは、とても強力で便利な機能なんだ。逆に言うと、オブジェクト指向モデリングが全盛の現代では、オブジェクト指向の範囲内でXMLも扱わないと、実用性が低くなってしまう。そのために敢えてXMLのスキーマ構造に対してオブジェクト指向を適用しようとするわけなんだ。

さらら: ..... (^ ^;

たけち: しかしXMLはオブジェクト指向だけを対象としているのではない。どちらかというと歴史的にはドキュメント指向のデータを扱ってきたし、そういうドキュメント指向のスキーマには、オブジェクト指向が必要としているとはまた別の表現能力を必要とされる。にもかかわらず、こういうオブジェクト指向では今ひとつうまく扱えないところまで、力づくでオブジェクト指向でまとめようとするから、どうしてもすっきりしない部分が出てくるんだね。

さらら: そっ、そう・・・(^ ^;

たけち

たけち: 逆にオブジェクト指向を直接的に扱わないRELAX NGなどでは、こういう力づくのところがないから、素直な記述ができる。しかしその反面、オブジェクト指向モデルをRELAX NGで書こうとすると、シームレスにできずにマッピング作業が必要になってくる。またその他には、ooRelaxNGというオブジェクト指向対応の別のスキーマ言語を用意して、それをRELAX NGへ変換する、といったアプローチも提唱されているんだね。このあたり、XML Schemaのようなアプローチと、RELAX NGやooRelaxNGのようなアプローチの、どちらがこれから主流になるかとか、どう使い分けて行くか、というのは、まだこれからの時代の流れを見ないと何とも言えないね。

たけち: ただ一つ言えるのは、XML Schemaは徹頭徹尾オブジェクト指向の考え方をもちこんだスキーマ言語であり、オブジェクト指向モデリングなどに強いスキーマ言語だということなんだ。

さらら: う〜ん、なんだか難しい話だわ。。。でも、要は、一見基準型がないように見えるけれど、本当はxsd:anyTypeが基準型になっていることが省略されている、ってことなのね!! (^ ^)v

さらら

たけち: えっ? そっ、そうだね・・・・・(^ ^;) (今まで一所懸命説明してきたことって、いったい・・・・・(^ ^; )

さらら: でも、わかったのはそれだけで、sequenceとかminOccursとかよくわからないんだけれど・・・・・

たけち: うん、今回はあくまで基本的な枠組みを説明してきただけだから、次回からそのあたりを詳しく勉強しようね。

さらら: は〜い!! (^ ^*

たけち: .......(こういうところがいいんだよな、さららって。 (^ ^; )

次回はsequence と minOccurs, maxOccursです 。。。。 (^ ^)v

たけち


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