前回に引き続き,今回もXML Schemaを使ったはてなダイアリー形式XML文書の構造定義を通して,XML Schemaの基本構文を学習します。

図1●はてなダイアリー形式XML文書の構造

例1 図1の構造のXML Schemaの定義例
※行番号は解説の便宜上付けたもので,実際のコードには必要ありません

[画像のクリックで拡大表示]

◇単純型の制限と拡張

 データ型に対して制約を加える場合には,「単純型の制限」を使用して定義します。例1の17行目にあるdate属性に設定できる値を "2007-02-01" のように年を4桁,月を2桁,日を2桁とし,年,月,日をハイフンで区切った値しか入力できないような制限を設けると,以下のようになります。

date属性の宣言

<xs:attribute name="date" type="dateType" use="required" />

date属性の入力制限

  <xs:simpleType name="dateType">
<xs:restriction base="xs:string">
<xs:pattern value="\d{4}-\d{2}-\d{2}|"/>
</xs:restriction>
</xs:simpleType>

 この場合は,新しい型を定義し,属性定義の中では,その新しい型の名前を指定します。複合型を定義する場合には,xs:complexType要素を使用しましたが,単純型を定義する場合には,xs:simpleType要素を使用します。また,型に対して制限を設定する場合には,xs:restriction要素を使用し,そのbase属性に単純型(組み込み単純型,または独自の単純型)を指定します。

 さらに,xs:restriction要素の子要素として,どのような制約を設定するかを記述していきます。この場合は,入力値に対する入力制限となりますので,xs:pattern要素を使用します。xs:pattern要素などのことを「制約ファセット」と呼びます。表1にまとめましたので,参照してください。

表1●主な制限ファセット
ファセット 意味
length 長さを固定する
minLength 最小の長さ
maxLength 最大の長さ
pattern パターン(正規表現)
enumeration 候補値
minExclusive 最小値(指定された値を含まない)
maxExclusive 最大値(指定された値を含まない)
minInclusive 最小値(指定された値を含む)
maxInclusive 最大値(指定された値を含む)

 単純型の要素に属性を追加する場合には注意が必要です。単純型の要素に属性を追加するのは「単純型の拡張」となります。例1の21行目のbody要素にcount属性を追加した例を以下に示します。

body要素にcount属性を追加した例

  <xs:element name="body" type="bodyType" />
<xs:complexType name="bodyType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute nane="count" type="xs:int" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:simpleType>

 この場合,属性を持つこととなり,定義としては複合型となりますが,要素の値としては単純型ですので,xs:complexType要素の子要素として,単純型を表すxs:simpleContent要素を記述します。さらに,拡張する場合には,xs:extension要素を記述し,その子要素にxs:attribute要素を記述します。

確認問題1
単純型の制限と拡張を定義する場合,使用する要素の組み合わせで正しいものを選択してください。なお,XML Schemaの名前空間接頭辞は「xs」とします。

(a)
 制限:xs:simpleType,xs:extension
 拡張:xs:complexType,xs:simpleType,xs:restriction

(b)
 制限:xs:simpleType,xs:restriction
 拡張:xs:complexType,xs:simpleType,xs:restriction

(c)
 制限:xs:simpleType,xs:restriction
 拡張:xs:complexType,xs:simpleContent,xs:extension

(d)
 制限:xs:simpleContent,xs:extension
 拡張:xs:complexContent,xs:simpleContent,xs:restriction

 正解は(c)です。単純型の制限は,xs:simpleType要素を使用し,その子要素にxs:restriction要素を用いて,(既存のデータ型(基底型)に制限を設定します。単純型の拡張は,xs:complexType要素を使用し,その子要素にxs:simpleContent要素を用いて,さらにその子要素にxs:extension要素で属性を追加します。(a)はxs:extension要素とxs:restriction要素が逆になっているので誤りです。(b)は拡張の部分にxs:restriction要素が記述されているので誤りです。(d)は制限の部分にxs:simpleContent要素,拡張の部分にxs:complexContent要素が記述されているので誤りです。

◇複合型の制限と拡張

 「複合型の制限」を使うことで,既存の型を再利用することができます。型に対して制限を加えるので,xs:restriction要素を使いますが,必ずxs:complexContent要素の子要素として記述します。

 例1の6行目~10行目のdiaryType型のday要素に出現回数の上限を500回に制限を設けると,以下のようになります。

例2 day要素の出現回数の制限

  <xs:complexType name="newDiaryType">
<xs:complexContent>
<xs:restriction base="diaryType">
<xs:sequence>
<xs:element ref="day" minOccurs="1" maxOccurs="500" />
</xs:sequence>
</xs:restriction>
</xs:complexContent>
</xs:complexType>

 複合型の制限を使用する場合,xs:restriction要素の子要素としてモデルグループを記述し,制限後の要素や属性の定義をすべて記述しなければなりませんので,注意が必要です。例えば,a要素,b要素,c要素の3つの要素を持つxType型のa要素だけに制限を設ける場合でも,制限を定義する型では,a要素,b要素,c要素の3つすべての定義を記述します。

 「複合型の拡張」も複合型の制限と同様に,既存の型を再利用でき,必ずxs:complexContent要素の子要素にxs:extension要素を記述します。複合型の拡張の場合は,拡張後の定義をすべて記述する必要はなく,追加する定義のみを記述します。追加の定義は,基底型の後ろに追加されます。

 以下の例は,例1の13行目~19行目のdayType型にcomment要素の定義を追加します。この例の場合,body要素の後にcomment要素を記述できるようになります。

例3 comment要素の追加

[画像のクリックで拡大表示]

 表2に型の制限と拡張について,まとめましたので参照してください。

表2●型の再利用
元の型 制限/拡張 制限/拡張後の型 用途
単純型 制限 単純型 データ型に制約を加える
拡張 複合型 要素の内容は文字列値で、その要素が属性を持つ
複合型 制限 複合型 型を再利用する
拡張 複合型 型を再利用する

確認問題2
複合型の拡張の定義として正しく記述されているものを選択してください。なお,XML Schemaの名前空間接頭辞は「xs」とします。

 正解は(d)です。複合型の拡張の定義ですので,複合型を定義するxs:complexType要素と内容が複合型であることを示すxs:complexContent要素を使用します。さらに拡張するには,xs:extension要素を使用します。(a)はxs:simpleContent要素が使われているので誤りです。(b)はxs:restriction要素が使われていますので複合型の制限となります。(c)はxs:simpleContent要素が使われていますので誤りです。(d)は複合型の拡張が正しく定義されています。

野中 康弘
インフォテリア 教育部 エンジニア。十数年間システム開発に携わり,そのうちの半分をデータベース管理者として奮闘する。現在は,インフォテリア認定教育センターのサポートや,XML技術者認定制度の「XMLマスター」に対応したコーステキストの開発などを担当している。