複数要素を定義する4つの基本形を覚えようSEのためのXML Schema入門(2)

この連載では、XML Schemaについて解説します。簡単なXMLの構造をXML Schemaにより記述できるようになることを目標に、XML Schemaの概要、要素・属性の定義、Complex TypeやSimple Type、属性グループについて解説していきます。連載を読むに当たり、整形式のXMLに関して十分理解していることを前提とします。

» 2004年01月07日 00時00分 公開
[小野彩子株式会社 四次元データ]

子要素を持つ要素のスキーマ定義

 前回「簡単なXML Schemaから始めよう」は、ルート要素が1つだけの簡単なXMLの構造をXML Schemaで記述しました。今回は複数の要素からなるXMLのXML Schemaでの定義について説明します。

 まずは、顧客データを表すXML文書(リスト1)のスキーマをXML Schemaで書いてみましょう。

<customer>
  <name>安登 マーク</name>
  <address>東京都千代田区丸の内3-3-1新東京ビル8F</address>
</customer>
リスト1 要素が複数あるXML文書(顧客XML)

 リスト1の顧客XMLは、要素が3つあるXML文書です。XMLの構造は、以下のようになっています。

要素名 特性
customer ルート要素。属性を持たない
name、addressの2つの子要素を持つ
name、addressの順に出現する
name
address
子要素、属性を持たない
内容には文字列のみ含まれる
図1 XML文書(リスト1)のツリー構造 図1 XML文書(リスト1)のツリー構造

 顧客XMLのスキーマをXML Schemaで表すと、リスト2のようになります。

 1: <?xml version="1.0"?>
 2: <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 3:   <xsd:element name="customer">
 4:    <xsd:complexType>
 5:      <xsd:sequence>
 6:        <xsd:element name="name" type="xsd:string"/>
 7:        <xsd:element name="address" type="xsd:string" />
 8:      </xsd:sequence>
 9:    </xsd:complexType>
10:  </xsd:element>
11: </xsd:schema>
リスト2 XML文書(リスト1)のスキーマ定義

単純型と複雑型

 customer要素は子要素を持ちます。子要素を持つ要素はXML Schemaでどのように宣言すればよいのでしょうか? 「要素がどのような子要素や属性を持つのか」「属性がどのような値を持つのか」を表すために、XML Schemaではデータ型を使用します。データ型には2種類あります。

  • 複雑型
    子要素または属性を持つ要素のデータ型

  • 単純型
    子要素および属性を持たない要素のデータ型、あるいは属性値のデータ型

 要素は複雑型か単純型かによって、宣言する方法が異なります。customer要素のように子要素を持つ要素は複雑型です。複雑型の要素を宣言する方法について見ていきましょう。

 XML宣言、xsd:schema要素を記述した後、3行目よりxsd:element要素を使用してcustomer要素を宣言します。

 3:   <xsd:element name="customer">

 name属性の値には、要素名「customer」を指定します。

複雑型を表す「complexType」

 複雑型の要素を宣言する場合は、xsd:complexType要素を使用します。

4:    <xsd:complexType>

 xsd:complexType要素はxsd:element要素の直下に記述します。

子要素の順番を指定する「sequence」

 xsd:complexType要素の内容(開始タグと終了タグの間)に、customer要素がどのような子要素を持つのか、記述します。

 5:      <xsd:sequence>
 6:        <xsd:element name="name" type="xsd:string"/>
 7:        <xsd:element name="address" type="xsd:string"/>
 8:      </xsd:sequence>

 xsd:sequence要素は子要素の順番を指定するXML Schemaの要素です。xsd:sequence要素の内容では、name、addressの順番に要素を宣言しています。これは、「顧客XMLでは、name要素、address要素の順に書かなければならない」ことを表しています。

子要素を宣言する

 name、addressなどの子要素は、xsd:sequence要素の内容(開始タグと終了タグの間)で宣言します。まず、xsd:element要素を使って、name要素を宣言します。

 6:        <xsd:element name="name" type="xsd:string"/>

 name属性の値に要素名「name」を記述します。name要素は子要素・属性を持たない、単純型の要素です。内容は文字列のみです。そこで、type属性を指定し、属性の値には「文字列」を表すデータ型、「xsd:string」を記述します。同じようにaddress要素も宣言します。

 7:        <xsd:element name="address" type="xsd:string"/>

 最後に、xsd:sequence、xsd:complexType、xsd:element、xsd:schema各要素の終了タグを記述して、XML Schemaの完成です。

 8:      </xsd:sequence>
 9:    </xsd:complexType>
10:  </xsd:element>
11: </xsd:schema>

より複雑なXMLのスキーマ定義

 今度はaddress要素にさらに子要素を追加してみましょう。

<customer>
  <name>安登 マーク</name>
  <address>
    <!-- address要素に子要素を追加する -->
    <prefecture>東京都</prefecture>
    <city>千代田区</city>
    <street>丸の内3-3-1新東京ビル8F</street>
  </address>
</customer>
リスト3 子要素を追加したXML文書

 このXMLの構造は以下のようになります。

要素名 特性
customer ルート要素。属性を持たない
name、addressの2つの子要素を持つ
name、addressの順に出現する
address 属性を持たない
prefecture、city、streetの3つの子要素を持つ
prefecture、city、streetの順に出現する
name
prefecture
city
street
子要素、属性を持たない
内容には文字列のみ含まれる
図2 XML文書(リスト3)のツリー構造 図2 XML文書(リスト3)のツリー構造

 要素の数が増えても心配はいりません。1つ1つの要素を順番に宣言していけばよいのです。リスト3のXML文書のスキーマをXML Schemaで表すと、以下のようになります。

1: <?xml version="1.0"?>
2: <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
3:
4:   <xsd:element name="customer">
5:     <xsd:complexType>
6:       <xsd:sequence>
7:         <xsd:element name="name" type="xsd:string"/>
8:         <!-- address 要素に子要素を追加する -->
9:         <xsd:element name="address">
10:          <xsd:complexType>
11:            <xsd:sequence>
12:              <xsd:element name="prefecture"
                              type="xsd:string"/>
13:              <xsd:element name="city"
                              type="xsd:string" />
14:              <xsd:element name="street"
                              type="xsd:string" />
15:            </xsd:sequence>
16:          </xsd:complexType>
17:        </xsd:element>
18:        <!-- ここまで -->
19:      </xsd:sequence>
20:    </xsd:complexType>
21:  </xsd:element>
22:
23:</xsd:schema>
リスト4 XML文書(リスト3)のスキーマ定義

 先ほどのリスト2のXML Schemaと比較すると、address要素の宣言の部分が異なります。8〜18行目でaddress要素を宣言しています。address要素は子要素を持つ複雑型の要素です。そこで、xsd:complexType要素を使用し、その内容で子要素(prefecture、city、street)について、宣言します。

ref属性で要素を参照

 リスト4のXML Schemaでは、address要素の宣言をcustomer要素の宣言の中に記述していました。すると、customer要素を宣言するxsd:element要素がとても大きくなってしまいました。このままでは、「customer要素がどんなデータ型なのか」非常に分かりづらいです。そこで、customer要素の宣言部分にはcustomer要素のデータ型のみを記述し、address要素については別の場所で説明しましょう。

1: <?xml version="1.0"?>
2: <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
3:
4:   <xsd:element name="customer">
5:     <xsd:complexType>
6:       <xsd:sequence>
7:         <xsd:element name="name" type="xsd:string"/>
8:         <xsd:element ref="address"/>
9:       </xsd:sequence>
10:    </xsd:complexType>
11:  </xsd:element>
12:
13:  <xsd:element name="address">
14:    <xsd:complexType>
15:      <xsd:sequence>
16:        <xsd:element name="prefecture" type="xsd:string"/>
17:        <xsd:element name="city" type="xsd:string" />
18:        <xsd:element name="street" type="xsd:string" />
19:      </xsd:sequence>
20:    </xsd:complexType>
21:  </xsd:element>
22:
23: </xsd:schema>
リスト5 ref属性を使ったスキーマ定義

 8行目でaddress 要素を宣言していますが、name属性を使用せずにref属性を使用しています。

8:         <xsd:element ref="address"/>

 ref属性を記述した場合、要素の構造については別の場所で宣言します。そして、ref属性の値に記されている要素を参照します。

図3 ref属性の宣言と参照先の記法 図3 ref属性の宣言と参照先の記法

 これは、「customer要素の2番目の子要素はaddress要素です。address要素に関しては別の場所に記述しています」という意味になります。そして、customer要素の宣言の後に、address要素の宣言を行います。

13:  <xsd:element name="address">
14:    <xsd:complexType>
15:      <xsd:sequence>
16:        <xsd:element name="prefecture" type="xsd:string"/>
17:        <xsd:element name="city" type="xsd:string" />
18:        <xsd:element name="street" type="xsd:string" />
19:      </xsd:sequence>
20:    </xsd:complexType>
21:  </xsd:element>

 ref属性を使用すると、たくさんの要素がある場合でもすっきりとしたXML Schemaを書くことができます。

属性を宣言する

 customer要素に属性を加えてみましょう。customer要素に、顧客IDを表すid属性を追加します。

<customer id="111111">
  <name>安登 マーク</name>
  <address>東京都千代田区丸の内3-3-1新東京ビル8F</address>
</customer>
リスト6 属性を持つXML文書

要素/属性名 特性
customer ルート要素。id 属性を持つ
name、addressの2つの子要素を持つ
name、addressの順に出現する
name
address
子要素、属性を持たない
内容には文字列のみ含まれる
id 属性値に任意の文字列を指定可能
図4 属性を持つXML文書(リスト6)のツリー構造 図4 属性を持つXML文書(リスト6)のツリー構造

 属性を追加する場合は、xsd:attribute要素を使用します。

 1: <?xml version="1.0"?>
 2: <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 3:
 4:   <xsd:element name="customer">
 5:    <xsd:complexType>
 6:      <xsd:sequence>
 7:        <xsd:element name="name" type="xsd:string"/>
 8:        <xsd:element name="address" type="xsd:string" />
 9:      </xsd:sequence>
10:      <!-- 属性を追加する -->
11:      <xsd:attribute name="id" type="xsd:string"/>
12:    </xsd:complexType>
13:  </xsd:element>
14:
15: </xsd:schema>
リスト7 属性を持つXML文書(リスト6)のスキーマ定義

 属性も、子要素と同じようにxsd:complexType要素の内容(開始タグと終了タグの間)で宣言します。属性は、子要素について記述した後(ここではxsd:sequence要素の後)で宣言します。

11:       <xsd:attribute name="id" type="xsd:string"/>

 属性は、xsd:attribute要素を使用して宣言します。属性の名前は、要素と同じようにname属性の値に指定します。ここでは「id」という名前の属性を宣言するので、name属性の値には「id」と記述します。属性のデータ型(属性値としてどのような値が記述できるか)は、type属性を使用して指定します。id属性は任意の文字列を属性値に指定できるので、type属性の値には「任意の文字列」を表すデータ型「xsd:string」を指定しましょう。

 属性が複数ある場合も、xsd:attribute要素を使用して属性宣言を繰り返していけば、属性をいくつでも指定できます。


 今回は子要素や属性を持つ要素を宣言する方法を説明しました。次回は、子要素の出現回数や出現の順番など、より細かく設定する方法について解説します。(次回に続く)

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。