名前付きモデルグループのネスト

2002年12月1日(日)更新


■XML Schemaではデータ型ありき

たけち: 今まで、「複合型内容を持った複合型」の「派生」について、いろいろと勉強してみてきたよね。

さらら: そうよね。でも、これで「複合型内容を持った複合型」の「派生」について自信がついたわ (^ ^*

たけち: そうだね。ただ、「派生」ではうまくいかない場合の対処の仕方も覚えておかないといけないね。

さらら: えっ?

たけち: 最初にXML Schemaでははじめにデータ型ありきという話をしたよね。

さらら: そうよね、それが基本的な考え方だったわね。

たけち: そして、自分で新しいデータ型を定義しようと思ったら、あるデータ型から派生させないといけないということも勉強したよね。

さらら: 実際、そうなんでしょ。今までそういうことばかり勉強してきたわ。

たけち: そうだね。こういう基本原則は厳としてXML Schemaには存在するわけなんだけれど、ただそれよりも低いレベル、つまりモデルグループのレベルで修正を加えるような方法もあるんだ。

さらら: ????

たけち


■オブジェト指向と再利用性

たけち: 今までXML Schemaについては「良くも悪くもオブジェクト指向」という表現で、その特徴を説明していたよね。

さらら: そうだったわ。

たけち: 何故、スキーマ言語にオブジェクト指向を取り入れたかということを考えると、現在、オブジェクト指向がソフトウェア開発の中心的なパラダイムになっている、という事情があるんだけれど...どうしてオブジェクト指向が中心的なパラダイムになったんだろうか?

さらら: え?(@o@) そんなことを言われても..... 要するにオブジェクト指向が便利だからでしょ。

たけち: そう「便利だから」なんだけど、どんなところが便利なのかわかるかい?

さらら: そんなのわからない...(^ ^; (いじわる)

たけち: オブジェクト指向の便利さというのは、いろいろな視点から語ることができるけれど、その便利さの一つは再利用性が高くなるということなんだね。

さらら: 再利用...

たけち: つまり一度書いたコードは、できるだけ使いまわそう、ということだね。

さらら: あっ、なるほど〜。そうそう。使い回しは大事だわよね。お中元、お歳暮のいらないのは使いまわさないといけないし、その包装紙もいろいろと再利用したいし、牛乳パックも再利用できるわよね。それから、ファストフード寿司を買った際についていたお椀も、食器として使いまわして...

たけち: さっ、さらら.....(^ ^;)

さらら: ...って、平成の世の主婦は言っているわよね(^ ^;)

さらら

たけち: まあ確かにそうだね(^^;) コンピュータの世界も同じで、大同小異のプログラムを次々に作っていては無駄が多いんだよね。そこで、ある機能を持ったコードの塊に名前をつけておいて用意しておき、それをある特定の用途に使う、つまりライブラリを利用するというのは、コンピュータプログラミングの基本なんだよね。
例えば最初にメジャーになったプログラミング言語のFORTRANでは、関数やサブルーチンという形でライブラリ化ができた。ただし、これは手続き、つまり動的な面でのライブラリ化だけだったんだ。
これがC言語あたりになってくると、構造体といったデータ型の集合が定義できるようになり、さらに少し遅れてからだけれど列挙型も使えるようになったね。でも、これらの静的な部分は、関数のような動的な部分とは、直接繋がっていなかった。
そして後のC++やJavaなどのようなオブジェクト指向プログラミング言語になってくると、この静的なデータ型の部分と、動的な関数(メソッド)の部分がセットになってクラスとなり、オブジェクト指向のクラスライブラリを形成していくんだね。

さらら: はっ、はぁ......(^ ^;)

たけち


■継承と派生

たけち: そして、静的なデータ型の部分と、動的な関数(メソッド)の部分がセットになったクラスを、カスタマイズするための手段が継承つまり、XML Schemaでいうところの派生なんだね。これによりクラスライブラリの再利用性を高めることができたんだね。

さらら: ふ〜ん、そうなの。

たけち: ところで、一般のオブジェクト指向プログラミング言語においては、クラスを構成している、「継承」などで追加できるようなデータ群の間には、そもそも「順番」「並び」といった考え方が存在しないんだ。どれが1番目で、どれが2番目で、どれが最後といった考え方が存在しない。例えば、あるクラスを拡張して、あるデータを追加した別のクラスを作ったとすると、その追加したデータは、従来あったデータと比べて最後の方に置かれる...などといった考え方そのものがないんだね。そういう「順番」「並び」といった考え方を、今までのオブジェクト指向プログラミング言語は持ち込まなかったし、持ちこまないからこそスムーズに処理できた、という面があるんだ。

さらら: ふ〜ん。

たけち: XML Schemaでは、オブジェクト指向の継承、つまり派生の考え方を導入することによって、単純型はうまくいったし、「順番」「並び」といった考え方がない属性でもうまくいったんだ。
ところが、内容モデルとしての要素にはしっかりと「順番」「並び」といった考え方があるんだよね(^^;) 要素の「順番」「並び」といった考え方を持ち込んで「継承」つまり「派生」を考えると、途端に難しくなる。だから、「複合型内容を持った複合型」の「拡張」では、

<xsd:sequence>
   基準型の内容モデル(モデルグループ)
   派生型で付け加えるモデルグループ
</xsd:sequence>

たけち:  という結果を求めることしかできなかったんだね。

さらら: あれは不便そうだったわ。


■(例)要素の前に要素を追加

たけち: そうだね。本来、オブジェクト指向を導入した目的として「再利用性を高める」ということがあったと思うんだけれど、それがある意味ではうまくいっていないわけなんだよね。そもそも「順番」「並び」といった考え方に対して、オブジェクト指向を適用しようという限界が、ここに現れていると言えるよね。

さらら: でも、以前代替グループを勉強したときには、綺麗にまとめられていたじゃない。

たけち: そう、あれは元々、オブジェクト指向的に解析できる問題だからこそうまくいったんだよ。ところが、何でもかんでもオブジェクト指向的に解釈できるわけじゃないんだね。例えば、次のようなXMLデータとXML Schemaを見てみようね。

さらら

XMLデータ例

<?xml version="1.0" encoding="Shift_JIS" ?>
<poem pno="8">
<yomi>熟田津に船乗りせむと月待てば潮もかなひぬ今は漕ぎ出でな</yomi>
<kana>熟田津尓 船乗世武登 月待者 潮毛可奈比沼 今者許藝乞菜</kana>
</poem>

XML Schema例

<?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:sequence>
  <xsd:element ref="yomi" />
  <xsd:element ref="kana" />
  </xsd:sequence>

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

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

</xsd:schema>

さらら: えぇ。これまで出てきた例ね。

たけち: これのyomi要素よりも前に作者を表すpoet要素を追加するにはどうしたらいいと思う?

さらら: えぇっ? う〜ん。。。。。PoemTypeを「拡張」しても無理なのよね。

たけち: そうだね、こういうスキーマの書き方ではちょっと無理だよね。でも、スキーマが次のようだったら、できる方法があるんだ。次のXML Schemaを見て。

XML Schema例(2): 名前付きモデルグループを使用

<?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:group ref="poemGroup" />
<xsd:attributeGroup ref="poemAttribute" />
</xsd:complexType>

<xsd:group name="poemGroup">
  <xsd:sequence>
  <xsd:element ref="yomi" />
  <xsd:element ref="kana" />
  </xsd:sequence>

</xsd:group>

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

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

</xsd:schema>


■名前付きモデルグループを使う

さらら: あっ、こんな書き方もできるのね。

たけち: そう、そしてこれをベースに次のように書き加えると、yomi要素よりも前に作者を表すpoet要素を追加することができるんだよ。

さらら

XML Schema例(3): yomi要素の前にpoet要素を追加

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

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

<xsd:complexType name="ExtendPoemType">
<xsd:group ref="extendPoemGroup" />
<xsd:attributeGroup ref="poemAttribute" />
</xsd:complexType>

<xsd:group name="extendPoemGroup">
  <xsd:sequence>
  <xsd:element ref="poet" />
  <xsd:group ref="
poemGroup" />
  </xsd:sequence>

</xsd:group>

<xsd:group name="poemGroup">
  <xsd:sequence>
  <xsd:element ref="yomi" />
  <xsd:element ref="kana" />
  </xsd:sequence>

</xsd:group>

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

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

</xsd:schema>

たけち: ここで見てもらいたいのは、次の個所だよ。

extendPoemGroup: yomi要素の前にpoet要素を追加

<xsd:group name="extendPoemGroup">
  <xsd:sequence>
  <xsd:element ref="poet" />
  <xsd:group ref="
poemGroup" />
  </xsd:sequence>

</xsd:group>

たけち: 名前付きモデルグループpoemGroupを参照して、新たな名前付きモデルグループextendPoemGroupを作っているね。これによって、yomi要素よりも前に作者を表すpoet要素を追加するということができたんだね。派生を使うよりも一段低いレベルで修正しているから、ちょっと面倒くさそうだけれど、でも、以前に定義したことを下敷きにできたんだ。この程度の例だとあまり有り難味がわかないけれど、もっと複雑な例だと、こういうテクニックが有効になってくるんだよ。

さらら: なるほど〜、こんなこともできるのね。

たけち: 今回の例は、「redefine」というテクニックと一緒に使うと、もっと有効なんだけれど、それについては後で説明するね。今日はこれでおしまい。次回は「ID型, IDREF型, IDREFS型」についてみてみようね。

さらら: は〜い。

次回は、ID型, IDREF型, IDREFS型です...... (^ ^)v

さらら


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