XMLフロンティア探訪
最終回 よく利用されるXML Schemaのデータ型(後編)

RELAX NGでは、外部のデータ型ライブラリとしてXML Schema Part 2で定義されているデータ型を利用できると前回説明した。しかしXML Schemaのデータ型はRELAX NGだけでなく、今後XMLが活躍する多くの場面で利用されるはずだ。今回はその後編、XML Schema Part2のデータ型を詳しく紹介していく。(編集局)

川俣 晶
株式会社ピーデー
2002/7/2

今回の主な内容
スキーマ言語による制約
組み込み派生データ型(前回の続き)
制約に使用される相

スキーマ言語による制約

 3回にわたり、新しいXMLのスキーマ言語であるRELAX NG(リラクシング)と、そこで使われるデータ型ライブラリであるXML Schema Part2を説明してきた。今回がその最終回だ。

関連記事:連載「XMLフロンティア探訪」
第11回 実は構文がまったく新しくなっているRELAX NG
第12回 どんなデータ型でも利用できるRELAX NG
第13回 よく利用されるXML Schemaのデータ型(前編)

 RELAX NGが持つ構文と、XML Schema Part 2の豊富かつ多機能なデータ型の組み合わせは、XML文書の型を定義するうえで非常に柔軟な表現を可能にする。例えば、あるXML文書中に年齢のデータを含ませたいとしよう。RELAX NGとXML Schema Part 2でこの文書型の定義を記述すれば、年齢が正の正数で表現されなくてはならないこと、200以上の数値がそこに記述されたときには不正な値として検出すること、などが実現できる。

 こうしたことがスキーマ言語で実現できるということは、XML文書を処理するアプリケーション側でいちいちチェックルーチンを書かなくとも済む、ということだ。スキーマ言語で文書型さえ定義しておけば、チェックはすべてXMLパーサが行ってくれるため、XMLアプリケーションの開発が楽になり、アプリケーションもシンプルになって、開発効率も上がる。

 では、具体的な例を示そう。RELAX NG内で、XML Schema Part 2のデータ型を使用し、相(facet)による制約を付加した例である。

 1: <?xml version="1.0"?>
 2: <grammar xmlns="http://relaxng.org/ns/structure/1.0">
 3:   <datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
 4:   <start>
 5:     <element name="person">
 6:       <element name="name">
 7:         <data type="string">
 8:           <param name="minLength">1</param>
 9:         </data>
10:       </element>
11:       <element name="age">
12:         <data type="nonNegativeInteger">
13:           <param name="maxExclusive">200</param>
14:         </data>
15:       </element>
16:     </element>
17:   </start>
18: </grammar>

 ここでは、人名が記述されるときには、必ず長さ1以上の文字列でなければならないこと、年齢は正の整数で、200歳以下であることなどが定義されている。順に見ていこう。

 3行目のdatatypeLibrary属性の指定により、XML Schema Part 2のデータ型の利用を宣言している。そして、7行目と12行目で記述されているstringとnonNegativeIntegerは、それぞれ前回と今回にわたって説明してきたデータ型である。

 8行目と13行目のparam要素で指定されているものが、相である。8行目では人名の長さは1文字以上でなければ意味がないということで、最小の長さに1を設定している。13行目では、いくらなんでも200以上は正しい年齢ではなく、何らかの間違いによる入力の可能性が高いので、有効な値ではないとしている。

 このスキーマに対して妥当なXML文書は、以下のようなXML文書である。

編集注:スキーマ言語によって文書型が定義されているXML文書を「妥当なXML文書」と呼び、スキーマ言語によって文書型が定義されてはいないが、XML文法に従って記述されているXML文書を「整形式なXML文書」と呼ぶ。

1: <?xml version="1.0" ?>
2: <person>
3:   <name>山田太郎</name>
4:   <age>17</age>
5: </person>

 一方、以下のXML文書は、name要素のstring型に付加されたminLength相の制約により妥当ではなくなる。名前を示すname要素の内容がないからだ。

1: <?xml version="1.0" ?>
2: <person>
3:   <name></name>
4:   <age>17</age>
5: </person>

 同様に、以下のXML文書は、age要素のnonNegativeInteger型に付加されたmaxExclusive相の制約により妥当ではなくなる。

1: <?xml version="1.0" ?>
2: <person>
3:   <name>山田太郎</name>
4:   <age>200</age>
5: </person>

 このように、スキーマ言語は単に文書型を示すだけではなく、その文書型に対してXML文書が妥当かどうかを判定できるため、不正なデータがアプリケーションに渡ることを事前に排除することができるわけだ。

 では、前回の続きとして、XML Schema Part 2のデータ型を詳細に見ていこう。

組み込み派生データ型(前回の続き)

ID

 NCName型より派生したデータ型である。ID型はXML 1.0勧告の、ID属性型を表現するデータ型である。ID型の値空間は、XML名前空間で定義されるNCNameに等しい。

 この型に付加できる相の一覧は以下のとおりである。

  • length
  • minLength
  • maxLength
  • pattern
  • enumeration
  • whiteSpace

IDREF

 NCName型より派生したデータ型である。IDREF型はXML 1.0勧告のIDREF属性型を表現するデータ型である。IDREF型の値空間は、XML名前空間で定義されるNCNameに等しい。

 この型に付加できる相の一覧は以下のとおりである。

  • length
  • minLength
  • maxLength
  • pattern
  • enumeration
  • whiteSpace

IDREFS

 IDREF型より派生したデータ型である。IDREFS型はXML 1.0勧告のIDREFS属性型を表現するデータ型である。IDREFS型の値空間は、IDREFをゼロ個ではない有限個数並べたものである。

 この型に付加できる相の一覧は以下のとおりである。

  • length
  • minLength
  • maxLength
  • enumeration
  • whiteSpace

ENTITY

 NCName型より派生したデータ型である。ENTITY型はXML 1.0勧告のENTITY属性型を表現するデータ型である。ENTITY型の値空間は、XML名前空間で定義されるNCNameに等しく、DTDで解析対象外実体として定義されていないものである。

 この型に付加できる相の一覧は以下のとおりである。

  • length
  • minLength
  • maxLength
  • pattern
  • enumeration
  • whiteSpace

ENTITIES

 ENTITY型より派生したデータ型である。ENTITIES型はXML 1.0勧告のENTITIES属性型を表現するデータ型である。ENTITIES型の値空間は、ENTITYをゼロ個ではない有限個数並べたものである。

 この型に付加できる相の一覧は以下のとおりである。

  • length
  • minLength
  • maxLength
  • enumeration
  • whiteSpace

integer

 decimal型より派生したデータ型である。小数部を0に固定したもので、一般的なプログラム言語などで使われる整数に相当する。integer型の字句空間は、0から9の文字の有限の列の前に符号が付いたものである。符号がない場合は“+”であると仮定される。

 この型に付加できる相の一覧は以下のとおりである。

  • totalDigits
  • fractionDigits
  • pattern
  • whiteSpace
  • enumeration
  • maxInclusive
  • maxExclusive
  • minInclusive
  • minExclusive

nonPositiveInteger

 integer型から派生したデータ型である。正ではない整数を表現する。正ではないという意味は、負数または0を表現するということである。その点で、負数だけを表現する次のnegativeIntegerと異なる。

 この型に付加できる相の一覧は以下のとおりである。

  • totalDigits
  • fractionDigits
  • pattern
  • whiteSpace
  • enumeration
  • maxInclusive
  • maxExclusive
  • minInclusive
  • minExclusive

negativeInteger

 nonPositiveIntegerから派生したデータ型である。負の整数を表現する。つまり、正の整数と0は有効ではないとするデータ型である。

 この型に付加できる相の一覧は以下のとおりである。

  • totalDigits
  • fractionDigits
  • pattern
  • whiteSpace
  • enumeration
  • maxInclusive
  • maxExclusive
  • minInclusive
  • minExclusive

long

 integer型から派生したデータ型である。値として、-9223372036854775808以上、9223372036854775807以下の範囲のみが有効とされるものである。

 この型に付加できる相の一覧は以下のとおりである。

  • totalDigits
  • fractionDigits
  • pattern
  • whiteSpace
  • enumeration
  • maxInclusive
  • maxExclusive
  • minInclusive
  • minExclusive

int

 long型から派生したデータ型である。値の範囲が-2147483648以上、2147483647以下の整数に制約されている。intとintegerは名前が似ているが、違う意味を持ったデータ型であることに注意が必要だ。またプログラム言語のよく似たデータ型と定義が一致しない場合があることも注意が必要だ。例えばVisual Basic .NETのInteger型に相当するのはinteger型ではなく、int型である。

 この型に付加できる相の一覧は以下のとおりである。

  • totalDigits
  • fractionDigits
  • pattern
  • whiteSpace
  • enumeration
  • maxInclusive
  • maxExclusive
  • minInclusive
  • minExclusive

short

 int型から派生したデータ型である。-32768以上、32767以下の整数に値の範囲が制約されている。

 この型に付加できる相の一覧は以下のとおりである。

  • totalDigits
  • fractionDigits
  • pattern
  • whiteSpace
  • enumeration
  • maxInclusive
  • maxExclusive
  • minInclusive
  • minExclusive

byte

 short型から派生したデータ型である。-128以上、127以下の整数に値の範囲が制約されている。

 この型に付加できる相の一覧は以下のとおりである。

  • totalDigits
  • fractionDigits
  • pattern
  • whiteSpace
  • enumeration
  • maxInclusive
  • maxExclusive
  • minInclusive
  • minExclusive

nonNegativeInteger

 integer型から派生したデータ型である。負ではない整数を表現する。つまり、0または正の整数である。

 この型に付加できる相の一覧は以下のとおりである。

  • totalDigits
  • fractionDigits
  • pattern
  • whiteSpace
  • enumeration
  • maxInclusive
  • maxExclusive
  • minInclusive
  • minExclusive

unsignedLong

 nonNegativeInteger型から派生したデータ型である。0以上、18446744073709551615以下の整数を扱う。符号なし整数と考えてもよい。

 この型に付加できる相の一覧は以下のとおりである。

  • totalDigits
  • fractionDigits
  • pattern
  • whiteSpace
  • enumeration
  • maxInclusive
  • maxExclusive
  • minInclusive
  • minExclusive

unsignedInt

 unsignedLong型から派生したデータ型である。0以上、4294967295以下の整数を扱う。符号なし整数と考えてもよい。

 この型に付加できる相の一覧は以下のとおりである。

  • totalDigits
  • fractionDigits
  • pattern
  • whiteSpace
  • enumeration
  • maxInclusive
  • maxExclusive
  • minInclusive
  • minExclusive

unsignedShort

 unsignedInt型から派生したデータ型である。0以上、65535以下の整数を扱う。符号なし整数と考えてもよい。

 この型に付加できる相の一覧は以下のとおりである。

  • totalDigits
  • fractionDigits
  • pattern
  • whiteSpace
  • enumeration
  • maxInclusive
  • maxExclusive
  • minInclusive
  • minExclusive

unsignedByte

 unsignedShort型から派生したデータ型である。0以上、255以下の整数を扱う。符号なし整数と考えてもよい。

 この型に付加できる相の一覧は以下のとおりである。

  • totalDigits
  • fractionDigits
  • pattern
  • whiteSpace
  • enumeration
  • maxInclusive
  • maxExclusive
  • minInclusive
  • minExclusive

positiveInteger

 nonNegativeInteger型より派生したデータ型である。最小値が1となり、0を含まず、正の整数のみが有効となる。

 この型に付加できる相の一覧は以下のとおりである。

  • totalDigits
  • fractionDigits
  • pattern
  • whiteSpace
  • enumeration
  • maxInclusive
  • maxExclusive
  • minInclusive
  • minExclusive

制約に使用される相

 相にはいくつかの種類があるが、最も頻繁に利用されるのは制約に使用する相だろう。ここまでの解説で出てきたものもそれに当たる。ここでは、制約に使用する相の種類を簡単に解説してみよう。

length

 この相は、データの長さを指定長に制約する。データの長さはnonNegativeInteger型で表現する。長さの単位は、それぞれのデータ型に依存する。string型ならXML勧告で定義される“Character”を単位とする。hexBinaryとbase64Binaryでは、バイナリデータのオクテット(バイト)を単位とする。

 この相には以下のコンポーネントが存在する。

  • value 長さを示すnonNegativeInteger型の値
  • fixed boolean値を指定する。trueなら、派生したデータ型では指定値を変更できない
  • annotation 注釈を記述する

minLength

 この相は、データの最小の長さを指定する。長さの単位はlengthと同様である。この相に存在するコンポーネントは、lengthと同じである。


maxLength

 この相は、データの最大の長さを指定する。長さの単位はlengthと同様である。

 この相に存在するコンポーネントは、lengthと同じである。


pattern

 データの妥当性を判定する正規表現を指定する。

 この相には以下のコンポーネントが存在する。

  • value 正規表現文字列
  • annotation 注釈を記述する

enumeration

 有効な値を列挙する。

 この相には以下のコンポーネントが存在する。

  • value 値が列挙されたanySimpleTypeに対応するデータ型を記述する
  • annotation 注釈を記述する

whiteSpace

 空白文字の扱いを指定する。空白文字の扱いにはいくつかの種類があるが、それを明示する必要のある場合に使用する。

 この相には以下のコンポーネントが存在する。

  • value preserve、replace、collapseのいずれかのキーワードを記述する。preserveは正規化を行わず、すべての空白文字を渡す。replaceは#x9(tab)、#xA(line feed) and #xD(carriage return)を、#x20(space)に置き換える。collapseはreplaceと同じ処理を行った後、複数の#x20(space)が連続している場合にそれを1個の#x20(space)に置き換える
  • fixed boolean値を指定する。trueなら、派生したデータ型では指定値を変更できない。
  • annotation 注釈を記述する。

maxInclusive

 maxInclusiveは指定値を含む最大値を指定する。例えば、maxExclusiveが100なら、100は正しい値である。

 この相には以下のコンポーネントが存在する。

  • value 最大値となる値を記述する。
  • fixed boolean値を指定する。trueなら、派生したデータ型では指定値を変更できない。
  • annotation 注釈を記述する。

maxExclusive

 maxExclusiveは指定値を含まない最大値を指定する。例えば、maxExclusiveが100なら、100は正しい値ではないが、99は正しい値である。

 この相のコンポーネントはmaxInclusiveと同じである。


minExclusive

 minExclusiveは指定値を含まない最小値を指定する。例えば、minExclusiveが100なら、100は正しい値ではないが、101は正しい値である。

 この相のコンポーネントはmaxInclusiveと同じである。


minInclusive

 minInclusiveは指定値を含む最小値を指定する。例えば、minInclusiveが100なら、100は正しい値である。

 この相のコンポーネントはmaxInclusiveと同じである。


totalDigits

 totalDigitsはdecimal型より派生したデータ型で、けた数を制約する。

 この相には以下のコンポーネントが存在する。

  • value positiveInteger型の値でけた数を指定する。
  • fixed boolean値を指定する。trueなら、派生したデータ型では指定値を変更できない。
  • annotation 注釈を記述する。

fractionDigits

 fractionDigitsはdecimal型より派生したデータ型の小数部のけた数を制約する。totalDigitsはpositiveInteger型なので0にできないが、fractionDigitsはnonNegativeInteger型なので0にできることに注意が必要である。つまり、けた数のない数値はあり得ないが、小数部がない数値はあり得る(整数になる)ということである。

 この相には以下のコンポーネントが存在する。

  • value nonNegativeInteger型の値で小数部のけた数を指定する
  • fixed boolean値を指定する。trueなら、派生したデータ型で指定値を変更できない
  • annotation 注釈を記述する

 非常に駆け足の要約になってしまったが、スキーマにおけるデータ型の表現力がDTDと比べて格段に向上していることの片りんはご理解いただけたかと思う。ただ、強力すぎることは、ときとして分かりにくさや、実装の困難さをもたらす場合もある。本当にXML Schema Part 2で定義されているデータ型や機能のすべてが必要とされているのかについては、異論もある。しかしXML Schema Part 2は、現在最も存在感の大きな2大スキーマ言語(XML SchemaとRELAX NG)の双方が利用するデータ型定義であり、XML Schemaのほかのパートよりも明らかに重要度は高いといえるだろう。

※連載「XMLフロンティア探訪」は今回が最終回です。長い間ご愛読ありがとうございました。川俣氏の新連載は現在企画中です、どうぞお楽しみに。

「連載 XMLフロンティア探訪」


XML & SOA フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

HTML5+UX 記事ランキング

本日月間