XMLマスターポイントレッスン ~ ベーシック編 ~
第5回 XML Schemaの基礎
インフォテリア認定教育センター 衣笠成一 KINUGASA, Seiichi
今回から3回にわたって、代表的なスキーマ定義言語の1つである「XML Schema」について解説していきます。主に、前回まで解説してきたDTDとXML Schemaでの定義の違い、XML Schemaを使った要素や属性の宣言について解説します。ベーシックV2試験のセクション4「XML Schema」を攻略する上で必須知識となりますので、しっかりと学習しましょう。
XML Schemaとは
前回まで、整形式XML文書やDTDを使った妥当なXML文書、XMLパーサーについて解説しましたが、DTDの特徴は、機能や定義内容がとてもシンプルであることです。したがって、さまざまな目的でXMLを使用するためには、DTDの機能や定義内容では不十分なケースが多く見受けられるようになりました。
これまで、XMLのスキーマ定義言語としてはDTDが標準でしたが、基幹業務システムなどでXMLの利用が急速に拡大し、その使用目的も多様化した結果、DTDでは機能が不足してきてしまいました。そこで、DTDに代わるスキーマ定義言語としてW3Cより勧告されたのが「XML Schema」です。XML Schemaが勧告されたことで、今後のスキーマ定義言語の標準として採用が進んできています。
XML SchemaとDTDの定義の違い
XML SchemaとDTDとでは、どのような定義の違いがあるのでしょうか。ここでは、社員情報に関するXML文書で説明します。
XMLのスキーマを定義する場合、まず、XML文書にしたい内容を箇条書きで書き出し(図1)、次に図1を元に図2のようなツリー構造を作成します。これによりXML文書の階層構造を把握でき、ここから実際にスキーマ定義言語を使ってスキーマ定義を行ないます。
図1:社員情報のスキーマ(文書形式)
[1] ルート要素は「社員情報」とする
[2] 「社員情報」の内容は「社員」が0回以上出現する
[3] 「社員」の内容は「名前」「所属」「電話」「メール」要素の順番で1回出現する
[4] 「名前」「所属」「電話」「メール」の内容は文字列とする
[5] 「社員」には「社員番号」という属性が存在する
[6] 「社員番号」の内容はint型で必須とする
図1や図2を元にDTDを使ってスキーマ定義を行なった例がLIST1、さらにLIST1をXML Schemaを使ってスキーマ定義を行なった例がLIST2です(employee.xs)。どうですか。まったく書き方が違いますね。DTDは独自の文法で記述しますが、XMLSchemaはXML 1.0の文法に準拠するXML形式で記述します。LIST2のXML Schemaに対して妥当なXML文書の例がLIST3です(employee.xml)。DTDの場合、XML文書との関連付けにはDOCTYPE宣言を使用しましたが、XML Schemaの場合、仕様ではXML文書の関連付けについては特に決められていませんので、実際には使用する妥当性検証ツールの実装方法に従います。ただし、XML Schemaの仕様では、XML文書と関連付けを行なうためのヒントを記述する方法が定義されています。XML文書のルート要素に以下の内容を挿入します。
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="employee.xs"
LIST1:社員情報のDTD
<!ELEMENT 社員情報(社員)*>
<!ELEMENT 社員 (名前, 所属, 電話, メール)>
<!ELEMENT 名前 (#PCDATA)>
<!ELEMENT 所属 (#PCDATA)>
<!ELEMENT 電話 (#PCDATA)>
<!ELEMENT メール(#PCDATA)>
<!ATTLIST 社員社員番号 CDATA
#REQUIRED>
LIST2:社員情報のXML Schema(employee.xs)
01 <?xml version="1.0" encoding="Shift_JIS"?>
02 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" >
03
04 <xs:element name="社員情報" type="EmployeeInfoType" />
05 <xs:complexType name="EmployInfoType">
06 <xs:sequence >
07 <xs:element ref="社員" minOccurs="0" maxOccurs="unbounded" />
08 </xs:sequence>
09 </xs:complexType>
10
11 <xs:element name="社員" type="EmployeeType" />
12 <xs:complexType name="EmployeeType">
13 <xs:sequence >
14 <xs:element ref="名前" />
15 <xs:element ref="所属" />
16 <xs:element ref="電話" />
17 <xs:element ref="メール" />
18 </xs:sequence>
19 <xs:attribute name="社員番号" type="xs:int" use=“required”/>
20 </xs:complexType>
21
22 <xs:element name="名前" type="xs:string" />
23 <xs:element name="所属" type="xs:string" />
24 <xs:element name="電話" type="xs:string" />
25 <xs:element name="メール" type="xs:string" />
26
27 </xs:schema>
(行番号は解説の便宜上付けたもので、実際のコードには不要です。)
LIST3:XML Schemaに対する妥当なXML文書(employee.xml)
<?xml version="1.0" encoding="Shift_JIS" ?>
<社員情報
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="employee.xs">
<社員社員番号="105">
<名前>岡村まさし</名前>
<所属>設計部</所属>
<電話>03-1452-4567</電話>
<メール>okamura@xmltr.co.jp</メール>
</社員>
<社員社員番号="109">
<名前>田中愛子</名前>
<所属>営業部</所属>
<電話>03-6459-98764</電話>
<メール>tanaka@xmltr.co.jp</メール>
</社員>
</社員情報>
「xsi:noNamespaceSchemaLocation=」の後に書かれている「“employee.xs”」が関連付けられたXML Schema文書のファイル名です。このXML文書をInternet Explorer(以下、IE)で開き(画面1)、IEの妥当性検証ツールでチェックしてみると画面2のような結果が返されます。ここまでのXML SchemaとDTDの違いを表1にまとめまし
たので、参考にしてください。
画面1:XML文書をIEで開いた状態(左)
画面2:IEの妥当性検証ツールによる検証結果(右)
表1:スキーマ定義におけるXML SchemaとDTDとの違い
XML Schema | DTD | |
文法 | XML 1.0の文法に準拠するXML形式 | XML 1.0の文法に準拠しない独自の文法 |
---|---|---|
XML文書との関連付け | ●使用する妥当性検証ツールの実装に従う ●関連付けのヒントとして、noNamespaceSchema Location属性などで定義できる |
DOCTYPE宣言を使用 |
XML Schemaの構造
ここからは、LIST2のemployee.xsファイルを例に、XML Schemaの書き方を説明します注1。
注1:今回掲載しているすべての構文(LIST)は、内容に合わせて一部を省略しており、構文のすべてではありません。ご了承ください。
XML Schemaのルート要素
ルート要素にはschema要素を使用し、XML Schemaの「名前空間」を宣言します。名前空間とは、XMLで定義された属性や要素の名前が重なることを避けるために用いる仕様で、通常はURL形式などで指定します。LIST2では、2行目の「xmlns:xs="http://www.w3.org/2001/XMLSchema」の部分が名前空間宣言です。また、xsは「名前空間接頭辞」と呼ばれ、その要素とその子要素で使用できます。一般的にはxsという接頭辞を使うことが多いです。
要素の宣言
要素の宣言を行なう場合、DTDではELEMENTキーワードを使用しますが、XML Schemaではelement要素を使用します。構文は図3のとおりです。しかし、要素に子要素がある場合とない場合とでは、宣言の仕方が違ってきます。
子要素がない場合は、22行目のように非常に簡単です。ここでは、name属性で要素名を指定し、type属性でデータ型を指定しています。
<xs:element name="名前" type="xs:string" />
DTDでは、要素の内容として#PCDATAという任意の文字列を示すことくらいしかできませんでしたが、XML Schemaではすべてデータ型として定義します。データ型は、表2に示すようなstring型、int型、日付型などをはじめ、ID型、NMTOKEN型といったDTD互換型など、あらかじめ定義された組み込み単純型注2で細かく指定できます。また、これらを組み合わせたり拡張、制限したりして、新しい型を独自に作ることもできます。
注2:XML Schemaの仕様には「Part1:Structures仕様」と「Part2:DataTypes仕様」があり、組み込み単純型とは、あらかじめPart2:DataTypes仕様で規定されているデータ型のこと。表2以外にも、16進表記のバイナリを表わす「xs:hexBinary」やBase64形式のバイナリを表わす「xs:base64Binary」などの型がある。
表2:組み込み単純型の例
●一般的なデータ型
名前 | 説明 |
xs:integer | 整数(無限精度) |
xs:positiveInteger | 正の整数(無限精度) |
xs:negativeInteger | 負の整数(無限精度) |
xs:nonPositiveInteger | 0を含む負の整数(無限精度) |
xs:nonNegativeInteger | 0を含む正の整数(無限精度) |
xs:byte | 8ビットで表わされる整数 |
xs:unsignedByte | 8ビットで表わされる整数(符号なし) |
xs:short | 16ビットで表わされる整数 |
xs:unsignedShort | 16ビットで表わされる整数(符号なし) |
xs:int | 32ビットで表わされる整数 |
xs:unsignedInt | 32ビットで表わされる整数(符号なし) |
xs:long | 64ビットで表わされる整数 |
xs:unsignedLong | 64ビットで表わされる整数(符号なし) |
xs:decimal | 10進数(無限精度) |
xs:float | 単精度浮動小数点数(32ビット) |
xs:double | 倍精度浮動小数点数(64ビット) |
xs:boolean | ブール値 |
xs:string | 任意の文字列 |
●日付や時刻を表わす型
名前 | 説明 |
xs:time | 時刻 |
xs:dateTime | 日付と時刻 |
xs:date | 日付 |
xs:gYear | 年 |
xs:gYearMonth | 年月 |
xs:gMonth | 月 |
xs:gMonthDay | 月日 |
xs:gDay | 日 |
●DTD互換型
名前 | 説明 |
xs:ID | XML 1.0仕様のID型 |
xs:IDREF | XML 1.0仕様のIDREF型 |
xs:IDREFS | XML 1.0仕様のIDREFS型 |
xs:ENTITY | XML 1.0仕様のENTITY型 |
xs:ENTITIES | XML 1.0仕様のENTITIES型 |
xs:NOTATION | XML 1.0仕様のNOTATION型 |
xs:NMTOKEN | XML 1.0仕様のNMTOKEN型 |
xs:NMTOKENS | XML 1.0仕様のNMTOKENS型 |
一方、要素に子要素がある場合は、まず、要素に新しいデータ型を指定します(11行目)。
<xs:element name="社員" type="EmployeeType" />
このtype属性で指定したものが「EmployeeType型」という複合型になります。11~20行目が複合型の宣言になります。実際には、この複合型の内容はcomplexType要素のname属性でEmployeeType型を指定し、子要素にモデルグループ(子要素の出現順序の設定方法)を指定しています。モデルグループには、DTDの「,」に相当する「記述した順序で出現させたい場合」はsequence要素を、DTDの「|」に相当する「いずれかで出現させたい場合」はchoice要素を指定します(表3)。
表3:モデルグループにおけるXML SchemaとDTDの違い
モデルグループの意味 | XML Schema | DTD |
要素が記述された順序で、指定された回数だけ出現 | sequence要素 | , |
要素のいずれか1つが、指定された回数だけ出現 | choice 要素 | | |
モデルグループの要素の宣言は、element要素のref属性を指定して、別の場所で宣言した要素を参照する方法が一般的です(LIST4)。要素の参照の構文は図4のとおりです。
LIST4:モデルグループの要素における要素宣言の参照
属性の宣言
属性の宣言を行なう場合、DTDではATTLISTキーワードを使用して宣言しますが、XML Schemaではattribute要素を使用します。構文は図5のとおりです。前述の複合型の宣言にもあるとおり、属性を記述する場合、複合型定義の内容の最後(モデルグループの後ろ)に記述することが約束ごとになっています(19行目)。
図5:attribute要素の構文
<xs:attribute name="社員番号" type="xs:int" use="required"/>
name属性で属性名、type属性でデータ型を指定します。また、オプションとして、use属性、default属性、fixed属性が指定できます。use属性は出現に関する指定でDTDの#REQUIREDに相当する「required(必須)」、DTDの#IMPLIEDに相当する「optional(任意)」が指定できます(表4)。何も書かない場合はoptionalです。そして、default属性では初期値を、fixed属性では固定値を指定でき、DTDの#FIXEDに相当します。
表4:属性の宣言におけるXML SchemaとDTDの違い
出現に関する指定 | XML Schema | DTD |
属性の記述が省略可能 | optional | #IMPLIED |
属性の記述が必須 | required | #REQUIRED |
属性の記述を禁止 | prohibited | なし |
繰り返し回数の指定
繰り返し回数の指定を行なう場合、DTDでは0回以上(*)か1回以上(+)と下限値を指定できるだけで、上限値は指定できませんでした。しかし、XML Schemaでは、minOccurs属性、maxOccurs属性を使用することで、1~3回や3~無制限というように細かく指定できます。上限値が無制限の場合は、maxOccurs属性に「unbounded」と指定します。
minOccurs属性、maxOccurs属性を省略した場合、両方ともデフォルト値が1である点に注意してください。繰り返しの指定は、要素の参照、属性の宣言、モデルグループ内で使用できます。
今月の確認問題
さて、ここまでXML SchemaとDTDの定義の違い、XML Schemaの要素の宣言、属性の宣言を解説してきましたが、みなさんはしっかり理解できましたか?ここで、今回解説した内容が理解できたかどうかを、確認問題で試してみましょう。
問題1
XML Schemaで日付や時刻を表わすための組み込み単純型として、正しいものを2つ選択してください。
- xs:date
- xs:gMonthYear
- xs:gMonthDay
- xs:timeDate
- xs:gDayMonth
解説
正解は、Aのxs:dateとCのxs:gMonthDayです。この2つが日付や時刻を表わす組み込み単純型です。よく使われる組み込み単純型は、一般的なプログラミング言語で使われているデータ型と同じです。また、既存のプログラミング言語やデータベースで使われている型にマッピングしづらい組み込み単純型は、あまり使われない傾向があります。
問題2
次の条件に合う正しいXML Schemaの記述を選択してください。なお、XML Schema名前空間の接頭辞は「xs」とします。
条件:「住所」属性を文字列型で省略可能で定義します。
- <xs:attribute name="住所"
type="xs:string" use="optional"/> - <xs:attribute name="住所"
type="xs:string" optional="true"/> - <xs:attribute name="住所"
type="xs:string" required="optional"/> - <xs:attribute name="住所"
type="xs:string" use="required"/>
解説
属性の出現に関する指定はattribute要素のuse属性で行ない、値としてoptionalを指定すると属性の記述が省略可能になります。そして、これは問題文中の条件を満たしていますので、Aは正解です。
attribute要素にoptional属性やrequired属性は存在せず、構文自体にも誤りがあります。したがってBとCは誤りです。
attribute要素のuse属性の値としてrequiredを指定すると、属性の記述が必須になります。構文としては合っていますが、問題文中にある条件「住所属性を文字列型省略可能で定義します」を満たしていません。したがって、Dも誤りです。
問題3
次のXML Schema文書の定義に従っているXML文書を1つ選択してください。
●XML Schema文書
<?xml version="1.0" encoding="Shift_JIS"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema" >
<xs:element name="社員" type="EmployeeType" />
<xs:complexType name="EmployeeType">
<xs:sequence maxOccurs="unbounded">
<xs:element ref="名前" />
<xs:element ref="所属" />
</xs:sequence>
</xs:complexType>
<xs:element name="名前" type="xs:string" />
<xs:element name="所属" type="xs:string" />
</xs:schema>
- <社員></社員>
- <社員>
<名前>田中まさし</名前>
<名前>岡村真紀子</名前>
</社員> - <社員>
<名前>田中まさし</名前>
<名前>岡村真紀子</名前>
<所属>営業部</所属>
<所属>経理部</所属>
</社員> - A、B、CのいずれもXML Schema文書の定義に従っていない
解説
このXML Schema文書で定義されている内容は、「社員」要素の子要素として「名前」要素と「所属」要素を持ち、「名前」要素、「所属」要素の順番で出現する、ということです。出現回数については、sequence要素のminOccurs属性が省略されていますので、「名前」要素と「所属」要素の組み合わせで1回以上、maxOccurs属性にunboundedが指定されていますので、無制限に出現します。また、このXML Schema文書をDTDに書き直すと<!ELEMENT 社員(名前,所属)+>になります。
Aは、「社員」要素の空要素ですので、XMLSchema文書で定義されている出現回数を満たしていません。したがってAは誤りです。Bは、「名前」要素のみが繰り返し出現し、所属要素が記述されていません。したがって、Bも誤りです。
Cは、先に「名前」要素が出現し、その後に「所属」要素が出現しており、「名前」要素と「所属」要素の組み合わせで出現していません。したがって、Cも誤りです。
よって、A、B、CのXML文書はXMLSchema文書の定義に従っていませんので、Dが正解となります。
* * *
今回は、XML SchemaとDTDの定義の違い、XML Schemaの要素や属性の宣言方法について解説しました。誌面の関係で今回は説明しませんでしたが、DTDは名前空間をサポートしておらず、XML Schemaは名前空間をサポートしています。また、要素の宣言でもdefault属性やfixed属性を指定できます。これらについても、各自でしっかりと押さえておきましょう。
次回はユーザー定義のデータ型を中心に、単純型の制限や拡張について解説していきます。
本誌付録CD-ROMに、本稿のサンプルコードとサンプルファイルを収録しています。また、DBマガジンのWebサイトからもダウンロードできます。
衣笠成一(きぬがさせいいち)
日本ヒューレット・パッカード株式会社HP教育サービス勤務。現在、インフォテリア認定トレーナーとして、XMLトレーニングコースを担当するとともに、大規模Web開発支援コースを含めたITプロフェショナル人材育成プログラムなどにおいて、技術サポートおよびトレーナー支援を行なっている。久しぶりの雑誌の記事執筆依頼で非常にプレッシャーを感じていますが、あと2回、頑張りたいと思っています。
<掲載> P.195-199 DB Magazine 2006 June