属性宣言: 属性の追加

2002年9月15日(日)更新


■単純型内容をもつ複合型

たけち: 今まで単純型を基準型にして「単純型内容をもつ複合型」を作ってきたけれど、今回は単純型内容をもつ複合型を基準型にして単純型内容をもつ複合型を作ってみようね。

さらら: えっ? ... (?_?;

たけち: あ、全然難しいことじゃないよ(^^;) 今までの単純な応用だよ。例えば

<yomi pno="28">
春過ぎて 夏来たるらし 白妙(しろたえ)の
衣干したり 天(あめ)の香具山(かぐやま)
</yomi>

 といった例で、

たけち

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

<xsd:element name="yomi" type="YomiType" />

<xsd:complexType name="YomiType">
    <xsd:simpleContent>
    <xsd:extension base="xsd:string">
    <xsd:attribute name="pno" type="xsd:positiveInteger" use="required" />
    </xsd:extension>
    </xsd:simpleContent>
</xsd:complexType>

</xsd:schema>

というふうに出てきたよね。

さらら: あっ、そっか。。。

たけち: ところで、これにさらに季節(season)という属性を追加したかったら、どういうXML Schemaを作ればいいんだろうか? ひとまずどんな歌にも季節があるわけではないから、出現は#IMPLIEDつまりuse="opitonal"としておくね。

    <yomi pno="28" season="夏">
        春過ぎて 夏来たるらし 白妙(しろたえ)の
        衣干したり 天(あめ)の香具山(かぐやま)
    </yomi>

さらら: え〜っと。。。。こうかしら。。

たけち

■YomiTypeをSeasonYomiTypeとして、season属性を追加( by さらら)
<?xml version="1.0" encoding="Shift_JIS" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="yomi" type="SeasonYomiType" />

<xsd:complexType name="SeasonYomiType">
    <xsd:simpleContent>
    <xsd:extension base="xsd:string">
    <xsd:attribute name="pno" type="xsd:positiveInteger" use="required"/>
    <xsd:attribute name="season" type="SeasonType" use="optional"/>
    </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>

たけち: そうだね。ところで、さららが今書いた方法は、前の(上の)YomiTypeを直接書き直して、SeasonYomiTypeとしてseason属性を追加しているけれど、今までのYomiTypeをそのまま残して、それを活かして新しいデータ型を作る方法があるんだよ。

さらら: えっ、どうするの?

たけち: うん、例えば次のようにするんだよ。

■YomiTypeを拡張(extension)
<?xml version="1.0" encoding="Shift_JIS" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="yomi" type="SeasonYomiType" />

<xsd:complexType name="SeasonYomiType">
    <xsd:simpleContent>
    <xsd:extension base="YomiType">
    <xsd:attribute name="season" type="SeasonType" use="optional"/>
    </xsd:extension>
    </xsd:simpleContent>
</xsd:complexType>

<xsd:complexType name="YomiType">
    <xsd:simpleContent>
    <xsd:extension base="xsd:string">
    <xsd:attribute name="pno" type="xsd:positiveInteger" 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>


■歌の関係

たけち: こういうふうに、今までのYomiTypeをさらに拡張(extension)しているんだよ。

さらら: なるほど、こうするのね。でも、こんなことができて何か良いことあるのかしら? これだったら最初から書き直した方が早くない?

たけち: そうだね。この程度の例ではそうだよね。それじゃあ前回の、あの属性がたくさんついたXML文書を元に考えてみよう。

さらら: !!(どきっ)......(やぶ蛇だったかしら (^ ^; )

たけち: まず前回は雑歌、挽歌、相聞歌、譬喩歌の4種類に分けて要素を変えたけれど、そもそもこの雑歌、挽歌、相聞歌、譬喩歌ってどういう関係にあるんだろうね?

さらら: 急に関係と言われても困るけれど.......要するにこういうことよね。万葉集の歌は大きく、雑歌、挽歌、相聞歌の3種類に分けることができて、それを三大部立と言うのよね。そして相聞歌の中で特に譬喩表現を使っているものを譬喩歌というのよね。

たけち: そうだね。この関係を図示すると次のようになっているんだね。

さらら: あっ、そうね。

さらら

歌の関連


■歌のクラス(UMLクラス図)

たけち: さて、この図を発展させて、UMLのクラス図というものを使って、もうちょっと詳しく、属性のことも含めて図示してみようか。

さらら: え゛っ?? UMLのクラス図ってなぁに。

たけち: あっ、ごめん。さっきの図をすこしきっちりと描いたものだから、いまはそんなに気にしなくていいよ。

さらら: えっ、えぇ。。

たけち

UMLのクラス図で表現した歌の関連

たけち: まず、すべての歌に共通する属性がこれだけあるんだよね。雑歌はそれをそのまま引き継ぐわけなんだけど、挽歌emotion属性がデフォルトで追悼になり、さらに、誰を追悼したいかというon属性が加わるね。
相聞歌emotion属性がデフォルトで恋愛になり、さらに、誰に贈答するかというsendTo属性が加わる。そしてそれらの属性はそのまま譬喩歌に継承されるわけだね。

さらら: へぇ〜なるほど。。。こういう図にするとわかりやすいわ。こういうのをクラス図っていうのね。でも派生の矢印が逆のように思うけど、どうなのかしら。

たけち: 今まで派生、つまりオブジェクト指向用語でいうところの継承は、今まで基準型 → 派生型ということばかり強調していたから、ちょっと違和感があるかもしれないね。でも、これは基準型、つまりオブジェクト指向用語でいうところのスーパークラスの方に矢印を向ける、という書き方にUMLクラス図では決まっているから、これはこれで慣れてね (^ ^;

たけち

さらら: ふ〜〜ん。。。。。。

たけち: .....(^ ^; じっ、じゃあ、まずこのPoemType型だけをXML Schemaで書いたらどうなるかな。

さらら: え〜っと、すべての歌に共通の属性を持っているPoemType型ね。こうかしら。。。。。。。

さらら

■PoemType型
<xsd:complexType name="PoemType">
<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:extension>
</xsd:simpleContent>
</xsd:complexType>

たけち: たけち: そうだね。じゃあ、最初に説明した属性を追加するテクニックを使って次のようにやってみよう。

  • PoemTypeを基準型にして
    MiscellaneousPoemType, ElegyType, LovePoemTypeを定義
  • LovePoemTypeを基準型にして
    MetaphoricalPoemTypeを定義

■歌のクラス図に基づいて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: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:extension>
</xsd:simpleContent>
</xsd:complexType>

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

<xsd:complexType name="ElegyType">
<xsd:simpleContent>
    <xsd:extension base="PoemType">
    <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="PoemType">
    <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="LovePoemType"/>
</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>

たけち: 最初の方はまだ習っていないテクニックを使っているから、これも無視してね (^ ^; それからPoemType定義にabstract="true"という属性が加わっているけれど、これも無視してね。見て欲しいのはMiscellaneousPoemType, ElegyType, LovePoemType, MetaphoricalPoemTypeを定義しているところだよ

さらら: わ〜、クラス図で示した関係から、そのまま定義することができたのね。

たけち: そうだね。こういうふうにオブジェクト指向の設計レベルのクラス図の形を、そのままXML Schemaに書くことができたね。このあたりがXML Schemaの優れた点なんだよ。

さらら: 関連を表した図から、そのままスキーマにできるという点が、属性グループ定義よりも優れているわけね。

たけち: 話をまとめてみると、DTDでは派生、つまりオブジェクト指向でいうところの継承の関係を扱うことができなかった。だから、共通する属性についてはパラメータエンティティを使う以外に方法がなかったんだよ。それに比べてXML Schemaの場合は、良くも悪くも「直接的にオブジェクト指向を扱っている」といえるんだよね。
以前、「『自分でXMLスキーマのデータ型を定義したければ、必ず他の何らかのデータ型を基準型として、そこから派生させるという形をとらない限り、自分でデータ型を定義することはできない』という基本原則(建前)がある」という話をしたよね。これが良くも悪くもXML Schemaの大きな特徴になっているんだ。

さらら

さらら: じゃあ、パラメータエンティティや属性グループ定義のような機能は、時代遅れで、使わない方がいいの?

たけち: 一概にそうとは言えないよ。まず世界を見渡すと、日本のソフトウェア業界ではオブジェクト指向モデリングの導入は消極的だけれど、欧米のソフトウェア業界ではもうオブジェクト指向モデリングは常識化して中心的なスタンダードな手法となっているんだね。そういうオブジェクト指向モデリングを中心に使っているところでは、直接、オブジェクト指向モデルからスキーマが書けるというのは、とても強力で便利な機能なんだ。でも、オブジェクト指向モデリングというのは決して万能というわけじゃないんだ。特にXMLは文書指向のスキーマも、データ指向のスキーマも書けるから、オブジェクト指向がすべてじゃないんだ。

さらら: 。。。。。 (^ ^*

たけち: だから、オブジェクト指向ではないところで、共通した属性について属性グループ定義を使うのは、それはそれで正しいんだよ。でも、オブジェクト指向でモデリングできるところで、わざわざ属性グループ定義を使うのはスマートじゃないよね。さっきも言ったように、XML Schemaは「直接的にオブジェクト指向を扱っている」スキーマ言語だから、オブジェクト指向でモデリングできるなら、それを使ったほうが素直だし綺麗にできるよね。結局、オブジェクト指向でモデリングできるかどうかも検討せずに、やみくもに属性グループ定義を使うのは良くない、という結論になるかな。

さらら: ふ〜ん。。。。。(何かわかったような、わからないような ... (^ ^; )

たけち: 今回は属性を追加したけれど、次回は逆に属性を削除するような話をするね。

さらら: は〜い。

次回の属性の削除につづきます 。。。。 (^ ^)v

たけち


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