グローバル属性 - xsi:type属性(1)

2003年6月15日(日)更新


■(XMLデータで)xsi:typeを使って、出現する要素のデータ型を指定

たけち: 今回は、一般にxsiという接頭辞で表される"http://www.w3.org/2001/XMLSchema-instance"の名前空間に属する4つのグローバル属性の最後、xsi:typeについて勉強することにするね。

さらら: はい。

たけち: このxsi:typeというグローバル属性は、検証の対象となるXMLデータ側で、それが出現している要素のデータ型を指定して変更できるグローバル属性なんだよ。

さらら: XMLデータ側で、それが出現する要素のデータ型を指定して変更できるなんて、どういう目的で使うの?

たけち: そうだね。このxsi:typeを使うようなケースというのは、大きく次の3つになるかなぁ〜。

  1. 同じ名前の要素が複数ある際に、その一部に、例外的な構造を要求する同一名の要素が存在する場合
  2. 代替要素を使うような場合に、要素名を変えずに属性で表現させたい場合。
  3. 複数のデータ型をとりうる場合に、そのどれかを指定する場合。
たけち

■例: 歌のコンテスト

さらら: う〜ん。。。これだけじゃ、何だかよくわからないわ・・・(^ ^;

たけち: じゃあ、実際の実例をみてみようね。まず1.だけれど、歌のコンテストを行って、特にその中でも優秀な歌には、金賞、銀賞、銅賞などが贈られたとしようね。XMLデータはこういうふうになるよ。

さらら

XMLデータ例: 歌のコンテスト(1)
<?xml version="1.0" encoding="Shift_JIS" ?>
<contest:poems xmlns:contest="http://www.example.com/competition"
     xsi:schemaLocation="http://www.example.com/competition   competition.xsd"

     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<contest:poem>目覚めれば ストーブの前 丸々と いびきごうごう 吾がお犬さま</contest:poem>

<contest:poem>木枯らしに 舞う紅葉(もみちは)と 電車待つ はしゃぐこどもの 吹く白き息</contest:poem>

<contest:poem prize="true" grade="金賞">もう寝たの そっと触れたる 妻の手の そっと答える 暖かさかな</contest:poem>

<contest:poem>はっきりと 好きと言えずに v(^ ^*)と 電子メールに 気持ち込めたの</contest:poem>

<contest:poem prize="true" grade="銀賞">吾が友と 共にリストラ この先も 共に歩まん 友ありてこそ</contest:poem>

<contest:poem>微笑んで 当たりますよう その笑顔 も一度見たく また買うジャンボ</contest:poem>

</contest:poems>

さらら: あら、おもしろいわね。

たけち: ここで注目して欲しいのは、gradeという属性は、金賞または銀賞または銅賞という値のどれかをとる属性なんだけれど、これが出現するのはprize="true"、つまり「これは受賞作ですよ」ということを示す属性が出現している場合だけ、ということなんだ。もし、prize属性が存在しないか、またはprize="false"であれば、gradeという属性自体が出現することはない、と考えているんだね。

さらら: それは分かるわ。でも、こういう属性の出現規則って、どう書けばいいのかしら?

たけち: うん、そういう規則はXML Schemaでは書けないよね(^ ^;)

さらら

■xsi:typeを使ったXMLデータの例

さらら: ぅぅ。。。XML Schemaでは書けないような例を出してどうするの?(ー ー;)

たけち: あ、いや、XML Schemaでは書けないけれども、xsi:typeを使えば、やりたいことが擬似的にできる、ということを言いたかったんだよ(^^;) 次の例を見てみてね。

XMLデータ例: 歌のコンテスト(2)
<?xml version="1.0" encoding="Shift_JIS" ?>
<contest:poems xmlns:contest="http://www.example.com/competition"
     xsi:schemaLocation="http://www.example.com/competition   competition.xsd"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<contest:poem>目覚めれば ストーブの前 丸々と いびきごうごう 吾がお犬さま</contest:poem>

<contest:poem>木枯らしに 舞う紅葉(もみちは)と 電車待つ はしゃぐこどもの 吹く白き息</contest:poem>

<contest:poem xsi:type="contest:受賞作" grade="金賞">もう寝たの そっと触れたる 妻の手の そっと答える 暖かさかな</contest:poem>

<contest:poem>はっきりと 好きと言えずに v(^ ^*)と 電子メールに 気持ち込めたの</contest:poem>

<contest:poem xsi:type="contest:受賞作" grade="銀賞">吾が友と 共にリストラ この先も 共に歩まん 友ありてこそ</contest:poem>

<contest:poem>微笑んで 当たりますよう その笑顔 も一度見たく また買うジャンボ</contest:poem>

</contest:poems>

さらら: さっきとほとんど同じXMLデータね。

たけち: そうだね。違うところはprize="true"と書かれていたところが、そのまま xsi:type="contest:受賞作"に置き換わっただけだよ。だから意味的には、さっきのXMLデータと同等だということが言えるよね。

さらら: えっ、えぇ。

たけち: でね。この場合は次のようにスキーマを書くことができるんだ。ちなみに、さっきのXMLデータと同じ名前空間に対して、違った接頭辞を割り当てているから気をつけてね(^^;)

XML Schema例: 歌のコンテスト 【competition.xsd】
<?xml version="1.0" encoding="Shift_JIS" ?>
<xsd:schema targetNamespace="http://www.example.com/competition"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema"
     xmlns:compe="http://www.example.com/competition">

<xsd:element name="poems" type="compe:PoemsType" />

<xsd:complexType name="PoemsType">
    <xsd:sequence>
        <xsd:element ref="compe:poem" maxOccurs="unbounded" />
    </xsd:sequence>
</xsd:complexType>

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

<xsd:simpleType name="PoemType">
    <xsd:restriction base="xsd:string" />
</xsd:simpleType>

<xsd:complexType name="受賞作">
    <xsd:simpleContent>
        <xsd:extension base="compe:PoemType">

        <xsd:attribute name="grade" type="compe:GradeType" />
        </xsd:extension>
    </xsd:simpleContent>
</xsd:complexType>


<xsd:simpleType name="GradeType">
    <xsd:restriction base="xsd:string">
        <xsd:enumeration value="金賞" />
        <xsd:enumeration value="銀賞" />
        <xsd:enumeration value="銅賞" />
    </xsd:restriction>
</xsd:simpleType>


</xsd:schema>

さらら: ふ〜ん。受賞作っていうデータ型があるわね。

たけち: そうそう。ここで注目して欲しいのは、
<xsd:complexType name="受賞作">
    <xsd:simpleContent>
        <xsd:extension base="compe:PoemType">

        <xsd:attribute name="grade" type="compe:GradeType" />
        </xsd:extension>
    </xsd:simpleContent>
</xsd:complexType>

という部分だよ。
PoemTypeを元にして、そこから派生させてgrade属性を付け加えた形で受賞作という名前のデータ型を定義しているね。

さらら: えぇ。。。でも、XMLデータの方には受賞作というような要素は無いわね。

たけち

たけち: そうなんだ。この受賞作という名前のデータ型は、それ自身は要素の宣言に使われてはいないけれど、

<contest:poem xsi:type="contest:受賞作" grade="金賞">もう寝たの そっと触れたる 妻の手の そっと答える 暖かさかな</contest:poem>

 と書くことによって、本来、grade属性を持たないPoemTypeで宣言されているcontest:poem要素が、ここではgrade属性を持った受賞作という名前のデータ型で宣言された要素に変身しているんだね。

さらら: へぇ〜。だからgrade="金賞" という属性が書けるってことなの?

たけち: そうなんだね。


■xsi:type属性を使って変更できるデータ型

さらら: 何か凄いわ。要素が、元々宣言されたデータ型と違うデータ型に変身してしまうのね。

たけち: そうだね。でもね、「元々宣言されたデータ型と違うデータ型に変身」させてしまう、と言っても、なんでもかんでも無闇にこういうことができるのじゃなくて、実はある一定の制限があるんだ。それは何かというと、

  • xsi:typeを使って変更できるデータ型は、元々宣言されたデータ型から派生したデータ型に限る


 ということなんだ。

さらら: なるほど。。。。。。

たけち: だから、
    <contest:poem xsi:type="xsd:float">1.23</contest:poem>
 というようなデータ型への変更は、この場合はいくら何でも無理なんだ。xsd:float型はPoemType型から派生してくるわけじゃないからね。

たけち

■名前空間の接頭辞にも注意しましょう

たけち: それから、故意に同じ名前空間に対して、XMLデータ側とスキーマ側で異なる接頭辞を使ったんだけれど、それに合わせて、xsi:typeの中の値の接頭辞も変わってくるんだよ。

さらら: えっ?

たけち: XMLスキーマ側ではcompeという接頭辞を使っている中で、「受賞作」という名前のデータ型を定義したけれど、XMLデータ側では同じ名前空間にcontestという接頭辞を割り当てたから、

    xsi:type="contest:受賞作"

 というふうに、値としての接頭辞も変更になったんだ。

さらら: へぇ〜、属性がとるべき値まで変更になってしまうのね。

さらら

たけち: 今までの例が「例外的な構造を要求する同一名の要素」の場合だけれど、そもそも「例外」がたくさんある場合は、それを「例外」とは呼ばないよね。この場合は、代替要素を使うような場合と似てくるんだ。

さらら: そっ、そうなの?

たけち: それについては次回にしようね。

さらら: あっ、は〜い。(^ ^*

次回は、xsi:type属性(2)です...... (^ ^;


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