2002年11月17日(日)更新 |
■歌集(poems)
さらら: 前回の「抽象的なデータ型」って、何かぴんと来なかったし、「抽象要素」に至っては、何故こんなものがあるのかさっぱりわからなかったわ。 たけち: あっ、ごめんね (^ ^; 確かにあれだけだと、ぴんと来なかったり、何に使うものなのかわからなかったりするよね。前回説明したことは、今回説明する代替要素とセットにすると、結構意味があることがわかると思うよ。そして前回の「抽象的なデータ型、抽象要素」にしても、今回説明する「代替要素」にしても、以前の説明でも使ったことがあって、説明を省いていただけなんだけれど、そのことについて今日はしっかり説明することにするね。まずは前回、こんなUMLのクラス図のスキーマを作ったよね。 |
さらら: そうね。図にするとこういう感じよね。 たけち: さて、この図に、複数の歌を羅列している歌集(poems)を加えてみることにするね。 |
さらら: えぇ・・・ たけち: この図に対応するようなXMLデータの例は次のようになるよね。 |
※歌集(poems)のXMLデータ例 |
たけち: このようにmiscellaneousPoemn、elegy、lovePoem、metaphoricalPoemはpoemsの子要素になるんだ。これを今までの知識でXML Schemaで書くとどうなるかな? さらら: えっ(^ ^; |
※歌集(poems)のXML Schema |
たけち: こんな感じだよね。さて、ここで見てもらいたいのが、 |
<xsd:complexType name="PoemsType"> |
たけち: の部分なんだ。PoemsTypeを構成する子要素4つがここに並べられているんだけれど、これが結構面倒くさいと思わないかい。 さらら: そう言われればそういう感じもするけれど、でも、仕方がないわよね。 たけち: ところがこの場合、もうちょっとすっきり書く方法があるんだ。例えば、さららが宴会の幹事をすることになったとするよね。ここでは仮に「万葉歌会」という会で宴会することにしとこうかな。宴会場となるところに「宴会をしたい」という申し込みをする場合、この「万葉歌会」に所属している参加者全員の名前、たとえば「さららと、たけちと、大伴家持と...が参加します」というふうに名前全部を挙げて「こういう人達で宴会するからね」と頼んだりするかい? さらら: そんなことは普通しないわ。普通、その宴会の主体となる組織の名前、会の名前で宴会を申し込むわよね。この場合「『万葉歌会』という会で宴会をしたいので、お願いしますね」というふうに頼むわね。そして出席者は当然皆「万葉歌会-会員」ということになるわね。 たけち: そうだね。そういう場合、普通参加者全員を含む「組織、会」の名前や「代表者」の名前で申し込むようなことをするし、出席者は皆「万葉歌会-会員」ということになるよね。さて、それと同様に、先ほどの例題も、「組織、会」の名前で登録することができるんだよ。要するに「さららと、たけちと、大伴家持と...が参加します」という方法ではなくて「出席者は万葉歌会-会員です」といった申し込み方ができるんだ。 |
■代替グループ
さらら: え、具体的にどうするの? たけち: まずはmiscellaneousPoem、elegy、lovePoem、metaphoricalPoemを含む一団を総称する名前としてpoemで登録してみる書き方をしてみようね。 |
<?xml version="1.0" encoding="Shift_JIS" ?> |
たけち: ここで注目してもらいたいのが、まず |
<xsd:element name="poem" type="PoemType" /> |
たけち: という部分なんだ。最初にpoemという要素をPoemType型として要素宣言をしている。そしてmiscellaneousPoem、elegy、lovePoem、metaphoricalPoemを要素宣言をしているところに、substitutionGroupつまり訳すると代替グループという属性があるよね。そこで総称名となるヘッド要素としてpoemを指定しているんだ。 さらら: こんなことをして、何になるの? たけち: これがさっきの例で言えば「たけちとさららと大伴家持は万葉歌会の会員ですよ」というふうに宣言しているような部分なんだ。そしてさらに次の部分も見てね。 |
<xsd:complexType name="PoemsType"> |
たけち: というところだよ。最初の例だと、内容モデルとして、 |
<xsd:complexType name="PoemsType"> |
たけち: として書かなければならなかった。つまり子要素になりうるものを全部書かないといけなかったわけだね。ところがさっきの書き方だと、内容モデルは、 |
<xsd:sequence minOccurs="0" maxOccurs="unbounded"> |
たけち: となっているね。つまりpoemという子要素が連続していくつも出現しても良いという書き方なんだけれど、そのpoem要素が出現するべき場所に代わりに代替グループとして設定されたmiscellaneousPoem、elegy、lovePoem、metaphoricalPoemといった要素が出現しても良い、ということなんだよ。 |
たけち: つまり、ヘッド要素という「総称名」が出現している部分に、ヘッド要素の代替グループになることを宣言した要素が出現してもよい、ということなんだ。こういう要素のことを代替要素と呼ぶんだよ。 さらら: あ、なるほど。 たけち: ここで注意して欲しいのは、代替グループのヘッド要素になれるのは、それらのデータ型と同じデータ型か、もしくはその基準型やさらにその先祖となっている基準型などで宣言された要素でないといけないということなんだ。つまり、同じデータ型で宣言されているか、もしくはそれらの派生関係の上の方にあるデータ型で宣言されていないとヘッド要素になれないんだね。 さらら: ふーん。 たけち: そして、さっきの書き方には実は致命的な問題点があるんだよ。 さらら: えっ?? |
たけち: 図に示したXMLデータ例をよく見て。
たけち: 出現して欲しいのは、miscellaneousPoem、elegy、lovePoem、metaphoricalPoemの4種類なんだけれど、それを総称した要素であるpoemも出現しているんだ。 先ほどの「万葉歌会」の例で考えると、「万葉歌会-会員」の会員として、僕やさららや大伴家持が宴会に出席するのは良いけれど、参加者の中に「万葉歌会-会員さん」という名前の人物まで参加してくるようなものだね(^^;) さらら: そうね。それって変だわ。。。。。じゃあこの方法は使えないのかしら。 |
■抽象的なデータ型、抽象要素を利用する
たけち: そんなことはないよ。そこで、必要になってくるのが前回学んだ「抽象的なデータ型、抽象要素」のテクニックだよ。 さらら: あっ! たけち: 「万葉歌会」というのは、歌を読む人たちの集まりの総称であって、「万葉歌会-会員さん」という名前の人物のような具体的な実体を伴うものじゃないんだ。つまり「万葉歌会-会員」というのは「抽象的な概念」なんだよね。ということは、XML Schema的に言うとabstract="true"という属性を伴うものなんだね。それと同様に、miscellaneousPoem、elegy、lovePoem、metaphoricalPoemの4種類を総称するpoemという要素、そしてそのデータ型であるPoemTypeも「抽象的な概念」で、XML Schema的に言うとabstract="true"という属性を伴うものなんだね。実際にこの属性を入れて書き直してみようね。 |
※歌集(poems)のXML Schema: 代替グループと抽象要素を使用 |
■代替グループ
たけち: この中で、 |
たけち:
後者はPoemTypeというデータ型が抽象的(abstract)なデータ型であることを示しているし、前者はそのPoemTypeで宣言されたpoemという要素が抽象的(abstract)な要素であることを示している。そしてこのpoemは、 さらら: あ、そういうわけなのね!! たけち: この場合のUMLのクラス図も描いておくね。最初の方に出したUMLのクラス図と比べてみてね。随分すっきりした感じになったよね。 |
さらら: なるほどねぇ〜。 たけち: それから、以前オブジェクト指向的に要素(モデルグループ)の追加をする際は、sequenceで囲まれた形になるので、choiceの内容をそのまま増やすことができない、という話をしたよね。だけど、代替要素を使うと、こういうオブジェクト指向的な関係なら、抽象的なデータ型から派生したデータ型の要素として、代替要素を後から増やすことができるよね。オブジェクト指向的にはこういう考え方で進める方が問題なく解決できるんだね。 さらら: こういうふうにすっきりと考えることができるわけなのね。納得したわ。 次は |
■補足: Javaの場合 |
たけち: このあたりはいかにもオブジェクト指向らしいテクニックになるから覚えておこうね。 さらら: またオブジェクト指向ね、ということは、Java... たけち: あ、そうだ、Javaでどうなるかも見ておこうね。 さらら: .......(やぶ蛇だったわ(^^;) ) たけち: Javaのようなオブジェクト指向プログラミング言語だと、スーパークラスのデータ型として宣言した変数が、サブクラスのインスタンスの値を取ることは一般的なんだよ。実際にJavaのプログラムを見てみようね。 |
class J31 { |
たけち: という感じかな。 さらら: え〜、わけがわからない! (^ ^; |
たけち: 理解する必要はないから、似ているところだけを見ていけばいいよ。例えば、 さらら: そう言われればそうねぇ〜。 |
たけち: abstract class PoemType{ さらら: そうね、そう言われれば似ているわね。 |
たけち: そして |
poem[0] = new MiscellaneousPoemType(1419,"未詳","鏡王女", |
たけち: という部分が実際のXMLデータである |
<miscellaneousPoem> |
たけち: に相当することになるんだ。 さらら: ふーん....。そうしたら代替要素にあたる部分はどこになるの? たけち: あ、それは存在しないよね。というか、それと同等の機能が最初から用意されているのが、Javaのようなオブジェクト指向プログラミング言語の特徴なんだよ。XML Schemaのようなオブジェクト指向スキーマ言語と、Javaのようなオブジェクト指向プログラミング言語の違いを考えると、後者はスーパークラス側で宣言された変数という条件だけで、こういうことができるのに対し、XML Schemaではその条件に加えて、今まで説明してきたように代替要素の指定をしないと、こういうテクニックが使えないという点が大きな違いになるね。オブジェクト指向プログラミング言語の変数と比べると、XML Schemaでは実際にどういう要素がどう出現するかということの方が一番の目的であるだけに、単に派生関係があるだけでは代替することは許可されないようになっているんだ。こういう違いがちょっと面白いよね。 さらら: そ、そうなの(よくわかんない(^^;) ) たけち: あ、まあ、Javaの話はあくまで参考程度の話で、これは特に理解しなくてもかまわないから(^^;) さらら: .......(また顔に出たかしら(^^;) ) |
■XMLスキーマのコーナーは、TAKABEさま(XSLTの遊び部屋)の全面的なご協力をいただいて作成しています。 |