この文書は、W3CのXML Schema Part 0: Primer草稿の翻訳である。正式な版は、W3Cのサイトにある英語版であってこの翻訳ではない。この翻訳は原文と技術的に等価なことを意図しているが, 翻訳上の誤りはあり得る。
原文はつぎのURLで参照することができる。
http://www.w3.org/TR/2000/WD-xmlschema-0-20000407/
訳者
Copyright © 1999 W3C® (MIT, INRIA, Keio), All Rights Reserved. 本文書には、W3C の責任範囲、商標、文書の使用、およびソフトウェアのライセンスに関する規定が適用される。
XMLスキーマ Part 0:入門書はXMLスキーマ機能の読みやすい記述を提供することを目的とした参考文書であり、XMLスキーマ言語を使ったスキーマ作成のしかたをすみやかに理解してもらうことを目指している。XML Schema Part 1: StructuresとXML Schema Part 2: DatatypesがXMLスキーマ定義言語を完全に規定した文書である。入門書は豊富な例(規定となるテキストへの多くのリンクで補完されている)によって言語の特徴を解説する。
XMLスキーマ Part 0:入門書はW3C XML 活動の一部である。
この文書はXMLスキーマ1.0の公開されたワーキングドラフトであり、一般及びWorld Wide Web Consortiumのメンバーによるレビュー用である。XMLスキーマワーキンググループはこの文書の公開に同意した。このドラフトの一部のセクションはXMLスキーマ仕様Part1とPart2で記述されているXMLスキーマ言語の最新の内容を反映していないかもしれないことに注意してほしい。わかっている不一致は文章中に記述されている。
この文書はいまだワーキングドラフトであり、一般(W3C外)または他のW3Cワーキンググループから経験やコメントに基づいて変更されるべきものであるが、W3Cワーキンググループは今後の本質的な変更を行うことを意図していない。
現在のW3Cワーキングドラフトのリストはhttp://www.w3.org/TR/で見ることができる。それらは更新され、置き換えられ、あるいはある時点で他の文書により時代後れなものになってしまっているかもしれない。 W3Cワーキングドラフトを参考文献として使ったり"作業中"以上のものとして引用したりするのは不適切である。
1 はじめに
2 基本概念: 注文書
2.1 注文書スキーマ
2.2 複合型定義, 要素と属性の宣言
2.3 単純型
2.4 名前を持たない型の定義
2.5 要素内容
2.5.1 単純型から複合型へ
2.5.2 空内容
2.5.3 混在内容
2.5.4 デフォルト内容
2.6 注釈
2.7 内容モデルを構築する
2.8 属性グループ
2.9 Null値
3. 高度な概念 I: 名前空間, スキーマと修飾
3.1 対象名前空間と、修飾されないローカル名
3.2 修飾されたローカル名
3.3 グローバル vs. ローカル宣言
3.4 宣言しない対象名前空間
4. 高度な概念 II: 国際的な注文書
4.1 複数文書中のスキーマ
4.2 拡張によって型を拡張する
4.3 派生型をインスタンス文書中で使う
4.4 制限によって複合型を派生する
4.5 同値クラス
4.6 抽象的な要素と型
4.7 派生型の作成と使用の禁止
5. 高度な概念 III: 四半期レポート
5.1 一意性を指定する
5.2 キーとその参照を定義する
5.3 XML Schemaの制約とXML 1.0のID属性との比較
5.4 型のインポート
5.5 Any要素、Any属性
5.6 schemaLocation
5.7 適合性
A. 謝辞
B. 単純型とそれらのファセット
C. 正規表現
D. 索引
E. 文書履歴(翻訳省略)
この文書、XMLスキーマ Part 0: 入門書はXML スキーマ定義言語に容易に 入門できるように記述されている。この文書はXML スキーマ仕様のPart 1 とPart 2に記 載されている正式な記述とともに使われるべきものである。本文書が想定して いる読者は、スキーマ文書を読み書きするプログラムの開発者、この言語の特 徴(特にDTDによって提供される以上の機能を提供する特徴)について知る必 要のあるスキーマの作者である。この文章は、読者がXML 1.0とXML-Namespacesについて 基本的に理解していることを仮定している。入門書のそれぞれの主要な節 はこの言語の新しい特徴を紹介し、具体例を用いてそれらの特徴を記述してい る。
2章は、XMLスキーマの基本的なメカニズムをカバーし ている。この節は、XML文書中に現れる要素と属性の宣言方法、単純型(simple type)と複合型の違い、複合型の定義、要素と属性の値に対する単純型の使用、 スキーマ中の注釈、要素と属性定義の再利用のための単純なメカニズム、null 値について記述している。
3章は、この入門書としては高度な内容を含んだ節であ り、名前空間がどのようにXMLスキーマ文書で使われるかについての基礎を説 明している。この節は、他の高度な概念を扱う節に現れる多くのトピックを理 解する上で重要である。
4章も、この入門書としては高度な内容を含んだ節で あり、既存の型から新しい型を派生するメカニズム、派生を抑制するメ カニズムを記述している。また、複数のソースからのスキーマの断片をまとめ あげるメカニズム、要素の置き換えのメカニズムについても記述している。
5章では、さらに進んだ内容を扱う。こ の節は、属性や要素の(値の)一意性を指定するメカニズム、ある名前空間の型 を他の名前空間から利用するメカニズム、名前空間に基づいて型を拡張するメ カニズム、文書の(スキーマとの)適合性をチェックする方法といった内容を含 んでいる。
上述の節に加えて、この入門書は多くの附属書を 含んでいる。 これらの付属書は、単純型及び(単純型に用いる)正規表現言 語に関する詳細な参照情報を提供する。
この入門書は、規定をするものではなく、XMLスキーマ言語の(W3Cとして ので)正規の仕様を提供するものではない。この文書中に含まれる例およびそ の他の説明材料は、読者のXMLスキーマの理解を助けるために用意されている が、常に決定的な答えを与えてくれるとは限らない。そのような場合、読者は XMLスキーマ仕様を参照する必要があるだろう。参照の助けとなるよう、筆者 らは仕様の関連する部分への多くのリンクを用意している。具体的には、要素 名及び属性の索引並びにデータ型の要約表をこの入門書に示し、本文中で言及したXML スキーマの項目からこれらへのリンクを張っている。表と索引からは、XMLス キーマ仕様Part1とPart2の関連するセクションにリンクしている。
スキーマの目的は、XML文書のあるクラスを定義することである。しばしば "インスタンス文書(instance document)"という言葉を用いて、特定のスキー マに適合するXML文書を表す。実のところ、インスタンスもスキーマも文書と して存在するとは限らない。それらはアプリケーション間で送られるバイトの ストリームやデータベースレコードのフィールドであったりXML情報セット (XML Information Set)で言うところの情報アイテム(information item)の集 まりであったりする。しかし、話を簡単にするためインスタンスやスキーマを それらがファイルであるかのように扱う。
po.xml というファイル中のインス
タンス文書を検討することから始めよう。この文書は家庭用品の注文と請求を
扱うアプリケーションが生成した注文書(Purchase Order)を記述している。
この注文書は、主な要素であるPurchaseOrderと、その子要
素であるshipTo, billTo, itemsか
ら構成されている。これらの子要素は他の子要素を含み、それらはさらに他の
子要素を含む。最後は、priceのように、子要素ではなく数字の
みを含んでいるような要素に行き着く。子要素又は属性をもつ要素は、複合型
(complex type)を持つという。一方、数字(あるいは文字列や日付等)を含むが
子要素を持たない要素は単純型(simple type)を持つという。いくつかの要素
は属性を持ち、属性は常に単純型を持つ。
このインスタンス文書におけるすべての複合型と、一部の単純型は注文書 のためのスキーマ中で定義されている。それ以外の単純型は、XMLスキー マに組み込み済みの単純型として定義されている。
注文書スキーマの内容を詳しく見る前に、インスタンス文書と注文書スキー マの関連付けについて少し触れておく。このインスタンス文書を見ればわかる ように、インスタンス中において注文書スキーマはまったく言及されていない。 実は、インスタンスからスキーマを参照する必要はない。多くのインスタンス はスキーマを参照するが、最初の節を簡潔にするために、ここでは参照を 省略している。インスタンス文書を処理するプロセッサは、インスタンス文書 からの情報なしでも注文書スキーマを得ることができると仮定している。後の節で は、インスタンスとスキーマを明示的に関連付けるメカニズムを導入する。
注文書スキーマはpo.xsdというファイルに格納されている。
注文書スキーマはschema要素とさまざまな子要素、特にelement,
complexType,
simpleTypeから構成されている。
これらの子要素が、インスタンス文書における要素の出現のしかたとその内容を決定する。
スキーマ中の各要素はxsd:という接頭辞(prefix)を持つ。この接頭辞はschema要素中の宣言xmlns:xsd="http://www.w3.org/1999/XMLSchema"によってXMLスキーマの名前空間と関連付けられている。任意の接頭辞が利用可能だが慣習として接頭辞xsd:をXMLスキーマの名前空間を示すために使う。同じ接頭辞、すなわち同じ関連付けがxsd:stringのような組み込み済みの単純型の名前にも現われる。この関連付けの目的は、要素と単純型が注文書スキーマ作者の語彙ではなく、XMLスキーマ定義言語の語彙に属することを明示することである。簡潔さのため、今後は要素と単純型を名前(例えばsimpleType)のみで参照し、接頭辞は省略することにする。
XMLスキーマでは、複合型と単純型は根本的に異なる。複合型は、要素を内 容として持ち、属性を持つことができる。単純型は、要素を内容として持つこ とができず、属性を持つこともできない。また、定義(definition)と 宣言(declaration)との間にも大きな違いがある。定義は、(単純型で あれ複合型であれ)新しい型を作る。宣言は、特定の名前と型をもった要素や 属性が文書インスタンスにおいて出現できるようにする。この節では、複合型 を定義すること、複合型の中に現われる要素や属性を宣言することに焦点をあて る。
新しい複合型はcomplexType要素を用いて定義され、
通常その定義は要素宣言(element declaration)、要素参照(element
reference)、属性宣言(attribute declaration)といったものの集まりを含ん
でいる。宣言はそれ自体は型ではなく、名前と制約(constraint)との関連付け
である。制約は、スキーマによって制御される文書中でその名前がどう出現
するかを制御する。要素はelement要素によって宣言され、属性は
attribute要素によって宣
言される。例えば、Addressは複合型として定義されており、
Addressの定義の中に5個の要素宣言と1個の属性宣言がある:
| Address型の定義 |
<xsd:complexType name="Address" >
<xsd:element name="name" type="xsd:string" />
<xsd:element name="street" type="xsd:string" />
<xsd:element name="city" type="xsd:string" />
<xsd:element name="state" type="xsd:string" />
<xsd:element name="zip" type="xsd:decimal" />
<xsd:attribute name="country" type="xsd:NMTOKEN"
use="fixed" value="US"/>
</xsd:complexType>
|
この定義が意味するのは、型がAddressであると宣言されている要素(例えばpo.xml中のshipTo)が
インスタンス中に出現するときは、必ず5つの要素と1つの属性で構成されていなければならないということである(訳注 正確には属性はオプションである)。これらの要素は、宣言のname属性の値で指定されているようにname, street, city, state, zipという名前を持つ。それらの要素のうち最初の4つはそれぞれ文字列を含み、5番目の要素は10進数を含む。Address型であると宣言されている要素は、countryという名前の属性を持ってもよいが、
その値はUSという文字列でなければならない。
Addressの定義はstring,
decimal, NMTOKENといった単純型を伴う宣言のみを含んでいる。一方、下のPurchaseOrderTypeの定義はAddressのような複合型を使った要素宣言を含んでいる。ただし、単純であるか複合であるかの違いはあるが、
どちらの宣言も型を同定するのに同じtype属性を用いていることに注意。
| PurchaseOrderTypeの定義 |
<xsd:complexType name="PurchaseOrderType">
<xsd:element name="shipTo" type="Address" />
<xsd:element name="billTo" type="Address" />
<xsd:element ref="comment" minOccurs="0" />
<xsd:element name="items" type="Items" />
<xsd:attribute name="orderDate" type="xsd:date" />
</xsd:complexType>
|
PurchaseOrderTypeの定義において、要素宣言のうちの二つ
(shipToとbillToに対するもの)は異なる要素名
を同じ複合型Addressに関連付けている。この定義の結果として、
(1) インスタンス(例えばpo.xml)中
に現われる、型がPurchaseOrderTypeであると宣言されている要
素は、shipToとbillToという要素を含んでいなけ
ればならない、(2) それぞれの要素は、Addressの一部として宣
言された5 つの子要素 (name, street,
city, state, zip) を含んでいな
ければならない。shipToとbillTo要素は
Addressの一部として宣言されたcountry属性も持っ
ていてよい。
PurchaseOrderTypeの定義はorderDate属性の
宣言を含んでいるが、それはcountry属性の宣言と同様に単純型
を指定している。実は、すべての属性宣言は単純型を参照しなければならない。
なぜなら、要素宣言と異なり、属性は他の要素や他の属性を持つことができな
いからである。
ここまで見てきた要素宣言は、名前を既に定義された型 と関連付けていた。しかし、新たに要素を宣言するより、既存の要素を利用し たほうが望ましいことがしばしばある。例えば:
<xsd:element ref="comment" minOccurs="0" />
この宣言は注文書スキーマのどこかで宣言されている既存の要素
commentを参照している。一般にref属性は、グローバルな要素を参照しな
ければならない。すなわち、複合型の定義の一部ではなくschema要素の下で宣言されているもので
なければならない。この宣言は、commentという要素がインスタ
ンス文書中に出現してもよく、その内容は要素の型(この場合はstring)と合致していなければならない、という
ことを示している。
要素と属性のどちらもグローバルに宣言することができる。
commentはグローバルな要素の一例であり
PurchaseOrderType定義に含まれている要素宣言から参照されて
いる。同様にschema要素の下
に属性を宣言し、それを型定義中の属性宣言からref属性を用いて参照することができる。
comment要素は
PurchaseOrderTypeの中で省略可能である。なぜなら定義中
のminOccurs属性の値が0
だからである。minOccursの値が1なら、その要素
は必須である。ある要素が出現してよい最大の回数は宣言中のmaxOccurs属性の値によって決定さ
れる。この値は41のような正の整数値か、出現回数の上限がないことを示す語
unboundedである。minOccursのデフォルト値は1だが
maxOccursに対するデフォ
ルト値はない。要素がmaxOccurs属性なしで宣言されてい
る場合、その要素の最大出現回数はminOccurs属性の値に等しい。
minOccurs属性も省略さ
れている場合にはその要素は1回だけ出現しなければならない。
属性は1回だけ出現するかもしれないか全く現われない
か(これがデフォルト)のどちらかである。そのため、属性の出現に関する指定
を行う構文は、要素に関する構文とは異なっている。特に、属性が
requiredなのかoptionalなのか、
optionalなら値はfixedなのかそれとも
defaultがあるのかを属性宣言中で指定するには、use属性を使う。2番目の属性valueは、必要な値を示す。
po.xsdの例は、country
属性の宣言を含んでおり、fixed という値のuse属性、US という値の
value属性とともに宣言され
ている。この宣言は、country属性は出現しなくてもよく、もし
出現するのならその値はUSでなければならず、出現しない場合
はその値を持ったcountry属性をスキーマプロセッサが生成する
ことを意味している。
要素および属性の出現を制限するために要素宣言と属性宣言のなかで使われる属性の値を表1にまとめておく。
| 表1. 要素と属性に対する出現の制約 | ||
|---|---|---|
| Elements (minOccurs, maxOccurs) fixed, default |
Attributes use, value |
Notes |
| (1, 1) -, - | required, - | 要素/属性は一度だけ出現しなければならない。任意の値を持つことができる |
| (1, 1) 37, - | required, 37 | 要素/属性は一度だけ出現しなければならない。値は37でなければならない |
| (2, unbounded) 37, - | n/a | 要素は2回以上出現しなければならず、その値は37でなければならない。一般に minOccurs とmaxOccurs' は正の整数であってよい, また maxOccurs' の値は "unbounded"でもよい |
| (0, 1) -, - | optional | 要素/属性は一度出現してもよい。任意の値を持つことができる |
| (0, 1) 37, - | fixed, 37 | 要素/属性は一度出現してもよい。出現した場合、その値は37でなければならない |
| (0, 1) -, 37 | default, 37 | 要素/属性は一度出現してもよい。出現しなかった場合その値は37である。出現するなら、出現する指定された値である。 |
| (0, 2) -, 37 | n/a | 要素は1回か2回現れるか、あるいは全く現れない。出現しなかった場合その値は37である。出現するなら、指定された値である。一般に minOccurs とmaxOccurs' に正の整数を使ってよく, また maxOccurs' の値は "unbounded"を使ってもよい |
| (0, 0) -, - | prohibited, - | 要素/属性は出現してはならない |
これまで、われわれは新しい複合型(例えばPurchaseOrderType)をどのようにして定義するか、要素(例えばpurchaseOrder)と属性(例えばorderDate)をどのようにして宣言するか、といったことを説明してきた。これらの作業は名前付け(naming)を含んでおり当然次のような疑問が生じる。「二つのものに同じ名前が与えられたらどうなるのか」。その答えは「二つのもの」が何かということに依存するが、一般には二つのものが似たものであるほど衝突がおこるおそれが大きくなる。
同じ名前が問題を引き起こすことを説明するための例をいくつか示す。も し、二つのものというのがどちらも型だったとすると、つまりUS-Statesとい う複合型と同じUS-Statesという単純型を定義したとすると衝突がおこる。も し、二つのものというのが型と要素あるいは型と属性であれば、つまり Addressという複合型を定義してAddressという要素を宣言したとならば衝突は おこらない。もし同じ名前の二つの要素が異なる型の中で使われる(すなわち、ど ちらの要素もグローバルではない)ならば、例えばnameという要素をAddress 型の中で宣言し、2番目のnameという要素をItem型の中で宣言した場合、衝突 は起こらない。最後に、二つのものというのがどちらも型であり、一つはあな たが定義したもの、もう一つがXMLスキーマで定義されているものであった場 合、例えばあなたがdecimalという単純型を定義した場合、衝突はおこらない。 最後の例で明らかに矛盾しているのに衝突がおこらない理由は、二つの型が異 なる名前空間に属しているからである。スキーマと名前空間の使用については 後の節で解説する。
注文書スキーマはいくつかの単純型をもった要素と属性を宣言している。
これらの単純型のうちstringとか
decimal等のいくつかはXMLスキーマに
組み込み済みであり、他のものは組み込み済みの型から派生(derive)した
型である。例えば、partNum属性は、stringから派生した型Skuをもつ。
組み込み済みの単純型とそれから派生した型はどちらもすべての要素および属性
宣言のなかで使うことができる。表2はXML
スキーマに組み込まれているすべての単純型を各型の例とともに示している。
| 表 2. XMLスキーマに組み込み済みの単純型 | ||
|---|---|---|
| 単純型 | 値の例 | 説明 |
| string | Confirm this is electric | |
| boolean | true, false, 1, 0 | |
| float | -INF, -1E4, -0, 0, 12.78E-2, 12, INF, NaN | 単精度の32ビット浮動小数と等価、NaNは"数字以外"を意味する |
| double | -INF, -1E4, -0, 0, 12.78E-2, 12, INF, NaN | 倍精度の32ビット浮動小数と等価、NaNは"数字以外"を意味する |
| decimal | -1.23, 0, 123.4, 1000.00 | |
| timeInstant | 1999-05-31T13:20:00.000-05:00 | 世界時間(UTC)から5時間遅れの東部標準時における1999年5月31日午後1時20分 |
| timePeriod | 1999-05-31T13:20 | |
| month | 1999-05 | 1999年5月 |
| year | 1999 | 1999年 |
| century | 19 | 1900年代(訳注:1900年から1999年まで) |
| recurringDate | --05-31 | 毎年5月31日 |
| recurringDay | ----31 | 31日毎 |
| timeDuration | P1Y2M3DT10H30M12.3S | 1年2ヶ月3日と10時間30分12.33秒 |
| recurringDuration | --05-31T13:20:00 | 世界時間における毎年の5月31日午後1時20分、timeInstantのフォーマットに類似 |
| binary | 100010 | |
| uriReference | http://www.example.com/, http://www.example.com/doc.html#ID5 | |
| ID | XML 1.0における属性型ID | |
| IDREF | XML 1.0における属性型IDREF | |
| ENTITY | XML 1.0における属性型ENTITY | |
| NOTATION | XML 1.0における属性型NOTATION | |
| language | en-GB, en-US, fr | XML 1.0で規定されているxml:langの値 |
| IDREFS | XML 1.0における属性型IDREFS | |
| ENTITIES | XML 1.0における属性型ENTITIES | |
| NMTOKEN | US | XML 1.0における属性型NMTOKEN |
| NMTOKENS | US UK | XML 1.0における属性型NMTOKENS |
| Name | shipTo | XML 1.0で規定される名前(Name) |
| QName | po:Address | XML Namespaceで規定される名前(QName) |
| NCName | Address | XML Namespaceで規定されるコロンなし名前(NCName)、すなわち接頭辞とコロンのないQName |
| integer | -126789, -1, 0, 1, 126789 | |
| nonPositiveInteger | -126789, -1, 0 | |
| negativeInteger | -126789, -1 | |
| long | -1, 12678967543233 | |
| int | -1, 126789675 | |
| short | -1, 12678 | |
| byte | -1, 126 | |
| nonNegativeInteger | 0, 1, 126789 | |
| unsignedLong | 0, 12678967543233 | |
| unsignedInt | 0, 1267896754 | |
| unsignedShort | 0, 12678 | |
| unsignedByte | 0, 126 | |
| positiveInteger | 1, 126789 | |
| date | 1999-05-31, ---05 | 2番目の例は、毎月5日 |
| time | 13:20:00.000, 13:20:00.000-05:00 | |
| XMLスキーマとXML 1.0 DTDの間の互換性をとるために単純型 ID, IDREF, IDREFS, ENTITY, ENTITIES, NOTATION, NMTOKEN, NMTOKENSは属性中でのみ使われるべきである。 | ||
新しい単純型は既存の単純型(組み込み済みの型または
派生した型)から制限(restriction)と呼ばれる手法を用いた派生型として定義
される。新しい型は既存の型とは異なる名前でなければならず、新しい型値の
有効範囲は、既存の型のものを制限してもよい。新しい単純型を定義するのに
はsimpleType要素を用い
る。また、値を制限するには、一つかそれ以上の"ファセット(facet)"を適用
する。すべてのファセットのリストは 附属書
Bにある。
値の範囲が1から99(両端を含む)の
myIntegerという名前の新しい整数型を作ることを考えよう。こ
れを、組み込み済みの単純型であるintegerを基にして定義する。integerの値の範囲は1よりも小さく99よりも大
きい部分を含んでいる。myIntegerを定義するため、二つのファ
セットminInclusiveと
maxInclusiveを用いて
基底型(base type)であるintegerの値
の範囲を制限する。
| 範囲 1-99のmyIntegerを定義 |
<xsd:simpleType name="MyInteger" base="xsd:integer"> <xsd:minInclusive value="1"/> <xsd:maxInclusive value="99"/> </xsd:simpleType> |
この例はmyIntegerを定義するために使われた特定の基底型
とファセットの組み合わせを示している。組み
込み済みの単純型とファセットのリストを参照すれば他にも多様な組み合
わせがあることがわかる。
注文書スキーマはもう一つのより巧妙な単純型定義の例
を含んでいる。Sku (製品番号)という新しい単純型が、単純型
stringから派生している。さらに
Skuの値はpatternと呼ばれるファセットに正規表
現"\d{3}-[A-Z]{2}"を組み合わせることによって制限されてい
る。この正規表現は"3 桁の数字の後にハイフンが続きさらに2文字の大文字ア
ルファベットが続く"ことを示している。
| 単純型"Sku"の定義 |
<xsd:simpleType name="Sku" base="xsd:string">
<xsd:pattern value="\d{3}-[A-Z]{2}"/>
</xsd:simpleType>
|
この正規表現言語は附属書Cにより詳細に記述されている。
XMLスキーマは附属書
Bにリストされている14のファセットを定義している。その中でenumeration(列挙)ファセットは
最も便利なものの一つであり、booleanを除くほとんどすべての単純型の値を制
限するのに使うことができる。enumerationファセットは単純型に
対してとりうる(互いに異なる)値の集合を制限する。例えば、enumerationファセットを用いて
stringから派生した新しい単純型
US-Stateを定義することができる。US-Stateの値
は合衆国の州の標準の省略名でなければならない。
| 列挙ファセットの使用 |
<xsd:simpleType name="US-State" base="xsd:string"> <xsd:enumeration value="AK"/> <xsd:enumeration value="AL"/> <xsd:enumeration value="AR"/> <!-- and so on ... --> </xsd:simpleType> |
state要素宣言の中で使われているstring型は、US-Stateで置き換え
るのがより適切である。この置換えによって、state要素の有効
な値、すなわちbillToとshipToの子要素である
stateの値はAK, AL,
AR等の一つに制限される。一つの型に対して列挙される値はす
べて異なっていなければならないことに注意せよ。
表2に記述されている単純型の大部分、
decimalやNMTOKENなどはいわゆる原始型(atomic type)で
ある。XML Schemaに関する限り、原始型の値はこれ以上分割できないとみなさ
れる。一方、XML Schemaは3つの組み込み済みのリスト型(list type)、すなわ
ち原始型の列から成る型を持っている。例えば、NMTOKENSはリスト型であり、この型の要素は
"US UK FR"といった空白で区切られたNMTOKENのリストである。3つの組み込み済みの
リスト型とはNMTOKENS、IDREFS、ENTITIESである。
組み込み済みのリスト型を利用するだけではなく、既
存の原始型からの派生によって新しいリスト型を作り出すこともできる(複合
型からリスト型を作ることはできない)。例えば、myIntegerの
リストを作ることができる:
<xsd:simpleType name='ListOfMyIntType' base='myInteger' derivedBy='xsd:list'/>
インスタンス文
書における内容がListOfMyIntTypeに適合するような要素は次
のようになる。
<listOfMyInt>47 25 99 3 25 1</listOfMyInt>
いくつかのファセットlength、minLength、maxLength、およびenumerationを新しいリスト型の派
生のさいに適用することができる。例えば、ちょうど6つの州からなるリスト
を作るため、上の例と同様にUS-Stateを基底型として新しいリ
スト型を派生し、項目の数を6個に制限することができる。
| 米国の6つの州を表すリスト型 |
<xsd:simpleType name="SixUS-States" base="US-State" derivedBy="xsd:list"> <xsd:length value="6"/> </xsd:simpleType> |
この型を持つと宣言された要素は6個の項目を持たなければならず、かつ6個の項目のそれぞれは列挙された(原始)型
US-Stateの値でなければならない。
<sixStates>PA NY CA NY LA AK</sixStates>
原始型 stringからリスト型を派生できることに注意する。しかし、stringは空白を含んでいるかもしれず、空白はリスト型中の項目の区切りになる。基底型がstringで固定長のリスト型を使うときには注意が必要である。例えば、lengthファセットが3でリスト型が定義されている場合、次の3項目から成るリストは正しい。
Asia Europe Africa
しかし、次の"3項目"リストは正しくない。
Asia Europe South America
"South America"はリストの外では単独の文字列として存在できるが、リストの中に含まれた場合には、SouthとAmericaの間の空白が4番目の項目を作りだしてしまう。したがって、後の例は3項目リスト型に適合しない。
名前付きの型(たとえばPurchaseOrderType)をいくつか定
義し、それらの型をtype=構文
によって参照する要素(たとえばpurchaseOrder)を宣言するこ
とによってスキーマを構築することができる。このようなスタイルのスキーマ
構築は単純ではあるが、1回しか参照されず、制約(constraint) をほとんど含
まないような型を数多く定義する場合には煩雑になる。そのような場合には、
名前を持たない型(anonymous type)として定義すれば、名前を付けて明示的に
参照するというオーバーヘッドを避けることができる。
po.xsd中のItems型の
定義には、名前を持たない型を使った二つの要素宣言(itemと
quantity)が含まれている。一般に、名前を持たない型が用いら
れていることは、要素(または属性)宣言に"type="がないこと、宣言が名前なしの型定義を
含んでいることから分かる。
| 名前を持たない二つの型の定義 |
<xsd:complexType name="Items">
<xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:element name="productName" type="xsd:string"/>
<xsd:element name="quantity">
<xsd:simpleType base="xsd:positiveInteger">
<xsd:maxExclusive value="100"/>
</xsd:simpleType>
</xsd:element>
<xsd:element name="price" type="xsd:decimal"/>
<xsd:element ref="comment" minOccurs="0"/>
<xsd:element name="shipDate" type="xsd:date" minOccurs='0'/>
<xsd:attribute name="partNum" type="Sku"/>
</xsd:complexType>
</xsd:element>
</xsd:complexType>
|
item要素の場合、要素宣言は名前を持たない複合型を含んで
おり、この複合型は要素productName, quantity,
price, comment, shipDateと属性
partNumから構成される。quantity要素の場合、
要素宣言は名前を持たない単純型を含んでおり、この単純型はintegerの派生型であって、値は1から99の範囲
に制限されている。
注文書スキーマは、他の要素を含む要素(例えばitems)、属
性を持ちかつ他の要素を含む要素(例えばshipTo)、単純型の値
だけを含む要素(例えばprice)の例を数多く含んでいる。しかし、
属性を持つが単純型の値だけを含む要素、他の要素と文字の内容が混在したも
のを含む要素、内容を持たない要素等はまだ現れていない。この節では、内容
モデルのこれらのバリエーションについて調べてみよう。
まず、単純な値を含み属性を持つ要素を宣言する方法について考えてみよう。インスタンス文書においてこのような要素は以下のようなかたちで現われる。
<internationalPrice currency='EU'>423.46</internationalPrice>
注文書スキーマはそのための出発点としてprice要素を宣言している。
<xsd:element name="price" type="decimal"/>
さて、この要素に属性を与えるにはどうしたらよいだろう?前述のように単純型は属性を持てず、decimalは単純型である。したがって、属性宣言を持ち込むためには複合型を定義しなければならない。かつ、その内容を単純型であるdecimalにしたい。よって、問題は単純型であるdecimalをベースにしてどうやって複合型を定義するか?
ということになる。単純型 decimalから派生する新しい複合型として定義するというのが、その答えである。
| 単純型から複合型を派生 |
<xsd:element name='internationalPrice'>
<xsd:complexType base='xsd:decimal' derivedBy='extension'>
<xsd:attribute name='currency' type='xsd:string' />
</xsd:complexType>
</xsd:element>
|
新しい(名前を持たない)型を定義するためにcomplexType要素を用いる。そして
base属性の中でdecimalを参照して、
新しい型は単純型decimalから派生す
ることを示す。標準的な属性宣言によって、currency属性を追
加する。そして、われわれはこの属性を単純型に追加したいので、
derivedBy='extension'
と記述することによって、この意図を伝えなくてはならない(型の派生につい
ては4節で詳しく扱う)。このようにして宣言された
price要素は、さきの例のようにしてインスタンス文書中に出現す
る。
通貨単位と価格を、price要素の属性の値と内容の値とに分けるのではなく、どちらも属性として表したいと仮定する。例えば以下のような形式である。
<internationalPrice currency='EU' value='423.46' />
このような要素は内容を全く持たない。これを、内容モデルが空(empty)であると言う。
| 空の複合型 |
<xsd:element name='internationalPrice'>
<xsd:complexType content='empty'>
<xsd:attribute name='currency' type='xsd:string' />
<xsd:attribute name='value' type='xsd:decimal' />
</xsd:complexType>
</xsd:element>
|
注文書スキーマの構成要素は要素が子要素を含み、最もネストが深い子要素だけが文字データを含むという特徴を持っていた。XMLスキーマでは、最も深い子要素だけに文字データが限定されるのではなく、文字データが子要素と並んで出現するようにスキーマを構成することもできる。後者のスタイルの構成は、content属性のmixedという値によって可能になる。
例として、顧客への手紙の一部を考える。この例は、注文書に現れる要 素のいくつかを用いている。
| 顧客への手紙の一部 |
<letterBody> <salutation>Dear Mr.<name>Robert Smith</name>.</salutation> Your order of <quantity>1</quantity> <productName>Baby Monitor</productName> shipped from our warehouse on <shipDate>1999-05-21</shipDate>. .... </letterBody> |
テキストが要素と子供要素の間に現われていることに注意。具体的には、letterBodyの子供であるsalutation、quantity、productName, shipDateの間にテキストが現われている。また、テキストはletterBodyの子供の子供であるname要素の周りにも現われている。次のスキーマ断片がletterBodyを宣言している。
| 顧客への手紙スキーマの一部 |
<xsd:element name='letterBody'>
<xsd:complexType content='mixed'>
<xsd:element name='salutation'>
<xsd:complexType content='mixed'>
<xsd:element name='name' type='xsd:string'/>
</xsd:complexType>
</xsd:element>
<xsd:element name='quantity' type='xsd:positiveInteger'/>
<xsd:element name='productName' type='xsd:string'/>
<xsd:element name='shipDate' type='xsd:date' minOccurs='0'/>
<!-- etc -->
</xsd:complexType>
</xsd:element>
|
XMLスキーマの混在モデルはXML 1.0の混在モ デルとは根本的に異なることに注意せよ。XMLスキーマの混在モデルでは、 インスタンス中に出現する子供の要素の順番と数はモデルに記述されている順 番と数に一致しなければならない。対照的に、XML 1.0の混在モデルではイン スタンス中に出現する子供要素の順番と数を制限することはできない。つまり、 XML1.0が混在モデルに対して部分的なスキーマ検証しか提供していないのに 対して、XMLスキーマは完全なスキーマ検証をサポートしているのである。
前の節では、われわれは新しい複合型をcontent属性を参照することなしに定義していた。当然、それらの定義においてはどんな内容モデルが使われていたのかという疑問が生じる。複合型のデフォルトの内容モデルはelementOnlyと呼ばれ、複合型が要素と属性を含んでよい、ということを意味している。一般にmixedモデルとelementOnlyモデルが受容する内容はmixedモデルが要素の前、後、要素と要素の間に文字データが現われることを受容するという点を除いて同じである。
elementOnlyは複合型を他の複合型から派生するときに適用される内容モデルである。しかし、(2.5.1節で行ったように)複合型を単純型から派生するときの内容モデルはtextOnlyと呼ばれている。実際、textOnlyという語句を使って複合型を定義することができる。
| textOnly複合型 |
<xsd:element name='internationalPrice'>
<xsd:complexType content='textOnly'>
<xsd:attribute name='currency' type='xsd:string' />
</xsd:complexType>
</xsd:element>
|
このようにして定義された(名前を持たない)型の内容は何の制約もうけ
ない。したがって、要素の値は423.36でもよいが、どんな文字列であってもまっ
たく合法である。通常は、decimalや
string等の制約のある型定義を利用し
て、制約のない型を避けたほうが良い。
注釈は、人間の読者とアプリケーションのどちらにも
役立つ。XMLスキーマは、スキーマに注釈をつけるための三つの要素を提供し
ている。注文書スキーマでは、われわれはスキーマについての説明と著作権情
報とをdocumentation
要素の中に記述した。この要素は、人間の読者向けの情報を入れる場所として
推奨されている。
appInfo要素は注文書スキーマの中では
使われなかったが、ツールやスタイルシートや他のアプリケーションのための
情報を供給するために使用できる。appInfoの興味深い使用例はXML Schema
Part 2: Datatypesの単純型を記述している
スキーマである。このスキーマを記述する情報、例えば「特定の単純型に
どのファセットが適用可能か」がappInfo要素の中に表現されており、
XML Schema Part 2文書のためのテキストを自動的に生成するアプリケーショ
ンによってこの情報が使われている。
documentation要素とappInfo要素はどちらもannotation要素の子要素として出現する。annotation要素それ自体は、ほとんどのスキーマ構成要素の最初に出現できる。次の例は要素宣言と複合型定義の先頭に現われたannotation要素を示している。
| 要素宣言と複合型定義中の注釈 |
<xsd:element name='internationalPrice'>
<annotation>
<documentation>element declared with anonymous type</documentation>
</annotation>
<xsd:complexType content='empty'>
<annotation>
<documentation>empty anonymous type with 2 attributes</documentation>
</annotation>
<xsd:attribute name='currency' type='xsd:string' />
<xsd:attribute name='value' type='xsd:decimal' />
</xsd:complexType>
</xsd:element>
|
この他にも、schema、simpleType、attribute要素によって指定されるスキーマ構成要素の最初に、annotation要素は出現することができる。
注文書スキーマにある複合型のどの定義も、インスタンス文書中に出現
しなければならない要素列を宣言している。これらの型のいわゆる内容モデル
において、個々の要素は出現しなくてもよいと宣言することができ、minOccurs 属性の値0によって示す
(例えばcomment)。また、minOccursとmaxOccursの値によって出現回数を
制約することもできる。XMLスキーマは、内容モデル中に出現する要素のグルー
プに対しても制約をかけることができる。この制約は属性には適用されないこ
とに注意せよ。これらの制約としては、XML1.0で利用可能なものをそのまま採用し、
さらにいくつかの制約を追加している。
XMLスキーマでは要素のグループを定義し名前をつけることができる。そして、そのグループを複合型の内容モデルを組み立てるのに使うことができる(XML 1.0のパラメータ実体の通常の使いかたに似ている)。名前を持たない要素グループも定義でき、宣言されたときと同じ順番で要素が出現するように制約することができる(名前付きのグループの要素と同様)。あるいは、要素のうちどれか一つだけがインスタンス中に出現できるという制約を与えることもできる。
例によって説明するため、注文書スキーマの PurchaseOrderType定義を変更して二つのグループを導入し、注文書に別々の 二つの住所(品物の送付先と請求書の送付先)か一つの住所(送付先と請求先 が同じ場合)のどちらかを記述できるようにする。
| 入れ子になったChoiceグループとSequenceグループ |
<xsd:complexType name="PurchaseOrderType">
<xsd:choice>
<xsd:group ref="shipAndBill" />
<xsd:element name="singleAddress" type="Address" />
</xsd:choice>
<xsd:element ref="comment" minOccurs="0" />
<xsd:element name="items" type="Items" />
<xsd:attribute name="orderDate" type="xsd:date" />
</xsd:complexType>
<xsd:group name="shipAndBill">
<xsd:sequence>
<xsd:element name="shipTo" type="Address" />
<xsd:element name="billTo" type="Address" />
</xsd:sequence>
</xsd:group>
|
choiceグループ要素は、そ
の子供たちのどれか一つだけがインスタンス中に出現できることを意味する。
子供の一つは名前付きグループ
shipAndBill(shipToとbillToの要
素の列で構成されている)を参照する(choice要素の)内側の
group要素であり、もう一つの
子供はsingleAddressである。結果として、インスタンス文書に
おいて、purchaseOrder要素はsingleAddress要素
か、shipTo要素とbillTo要素の並びでなければな
らない。名前付きグループの内容モデルはデフォルトでsequenceなので
shipAndBillの定義中で使われているsequence要素は絶対に必要というわけ
ではない。
グループ中の要素への制約の加えかたとして三番目の
選択肢がある。どの要素も1回だけ出現するか全く出現しないかのどちらかで
あり、出現する場合はどんな順番でもよいという制約である。allグループ(SGMLの&- Connectorの簡
略化されたバージョンを提供する)はあらゆる内容モデルにおいてその最上位
レベルでのみ使うことができると制限されている。さらに、グループの子供は
すべて(グループではなく)個々の要素でなければならず、内容モデル中のど
の要素も1回より多く現れてはいけない。つまり、許されるminOccursとmaxOccursの値は0と1だけである。
例えば、purchaseOrderの子供要素が任意の順番で出現できるよ
うにするため、purchaseOrderTypeを次のように再定義すること
ができる。
| Allグループの例 |
<xsd:complexType name="PurchaseOrderType">
<xsd:all>
<xsd:element name="shipTo" type="Address"/>
<xsd:element name="billTo" type="Address"/>
<xsd:element ref="comment" minOccurs="0"/>
<xsd:element name="items" type="Items" />
</xsd:all>
<xsd:attribute name="orderDate" type="xsd:date" />
</xsd:complexType>
|
この定義は、comment要素はpurchaseOrder中
に現れても現れなくてもよく、現れるならshipTo,
billTo, itemsのいずれの前後でもよいが、現れ
るのは1回だけに限るという記述になっている。さらに、all グループに関する制限のため、
commentが2回以上現れてもよいようにグループの外で記述する
ことは許されていない(訳注: 繰り返しを指定することなどはできないという
意味)。XMLスキーマは、all グ
ループは内容モデルの先頭にただ一つの子供として現れなければならないと規
定している。言い換えれば、次の記述は正しくない。
| 正しくないAllグループの使用例 |
<xsd:complexType name="PurchaseOrderType">
<xsd:all>
<xsd:element name="shipTo" type="Address"/>
<xsd:element name="billTo" type="Address"/>
<xsd:element name="items" type="Items" />
</xsd:all>
<xsd:element ref="comment" minOccurs="0" maxOccurs="unbounded"/>
<xsd:attribute name="orderDate" type="xsd:date" />
</xsd:complexType>
|
最後に内容モデル中に現れる名前をもつグループ(groupで表現される)、名前を持たないグループ(chocie, sequence, allで表現される)はminOccursとmaxOccurs属性を持つことができる。XMLスキーマが提供するさまざまなグループを組み合わせ入れ子にすることにより、そしてminOccursとmaxOccursの値を指定することにより、XML
1.0 DTDで表現可能なすべての内容モデルを表現することができる。さらに、allグループはそれ以上の表現能力をもたらす。
注文書にある各項目についてのより詳細な情報を記述するため、在庫の有
無、重さ、望ましい出荷方法等を示す属性をitem要素に追加したい
と仮定しよう。これらの属性を追加する一つの方法は、属性宣言
をitemの型定義に追加することである。
| インライン型定義への属性の追加 |
<xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:element name="productName" type="xsd:string"/>
<xsd:element name="quantity">
<xsd:simpleType base="xsd:positiveInteger">
<xsd:maxExclusive value="100"/>
</xsd:simpleType>
</xsd:element>
<xsd:element name="price" type="xsd:decimal"/>
<xsd:element ref="comment" minOccurs="0"/>
<xsd:element name="shipDate" type="xsd:date" minOccurs='0'/>
<xsd:attribute name="partNum" type="Sku"/>
<xsd:attribute name="weight" type="xsd:decimal"/>
<xsd:attribute name="shipBy">
<xsd:simpleType base="string">
<xsd:enumeration value="air"/>
<xsd:enumeration value="land"/>
<xsd:enumeration value="any"/>
</xsd:simpleType>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
|
もう一つの方法は、これらの属性を含んだ名前付き属
性グループを作り、このグループをitem要素宣言の中から名前で
参照することである。
| 属性グループを使った属性の追加 |
<xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:element name="productName" type="xsd:string"/>
<xsd:element name="quantity">
<xsd:simpleType base="xsd:positiveInteger">
<xsd:maxExclusive value="100"/>
</xsd:simpleType>
</xsd:element>
<xsd:element name="price" type="xsd:decimal"/>
<xsd:element ref="comment" minOccurs="0"/>
<xsd:element name="shipDate" type="xsd:date" minOccurs='0'/>
<xsd:attributeGroup ref="ItemDelivery"/>
</xsd:complexType>
</xsd:element>
<xsd:attributeGroup name="ItemDelivery">
<xsd:attribute name="partNum" type="Sku"/>
<xsd:attribute name="weight" type="xsd:decimal"/>
<xsd:attribute name="shipBy">
<xsd:simpleType base="xsd:string">
<xsd:enumeration value="air"/>
<xsd:enumeration value="land"/>
<xsd:enumeration value="any"/>
</xsd:simpleType>
</xsd:attribute>
</xsd:attributeGroup>
|
このように属性グループを使うことによりスキーマの可読性が向上し、スキーマの更新が容易になる。なぜならば、属性グループは1個所で定義され編集され、複数の定義や宣言の中から参照され得るからである。これらの属性グループの特性はXML1.0のパラメータ実体と類似している。属性宣言も属性グループ参照も複合型定義の最後に現れなければならないことに注意する。
po.xml中にリストされている注文書
の項目の一つ、Lawnmower(芝刈り機)はshipDate
要素を持っていない。このシナリオの文脈では、スキーマ作者はそのような欠
落でそのitemがまだ出荷されていないことを示すつもりだった
のかもしれない。しかし、一般には要素の欠落は何ら特定の意味をもたない。
欠落は、情報が不明であるか、持ち得ない種類の情報であるかを示しているの
かも知れないし、他の理由で要素が欠落しているのかも知れない。
itemが出荷されていない、情報が不明である、持ち得ない種類
の情報である等を、要素の欠落によって表現するのではなく、要素によって
明示的に示すことがしばしば望ましい。例えば、関係データベース
とのやりとりでは、値が"null"であることを要素(明示的に存在する要素)に
よって表現し、送受信を行うことが望ましいかもしれない。XMLスキーマの
null機構は、null値を持った要素(もしくはnull値を持たない要素)が出現す
ることを可能にしており、このような場合を表現することができる。
XMLスキーマのnull機構は、nullであることを示す外付
けのシグナルである。言い換えれば、要素内容として実際に出現するようなnull値
があるわけではなく、要素内容がnullであることを示す属性が代わりに存在す
る。説明のため、shipDate要素宣言を内容がnullであることを
伝えられるように変更する。
<xsd:element name="shipDate" type="xsd:date" nullable="true"/>
インスタンス文書においてshipDateがnull値を持つことを明示的に表現するために、null属性(XMLスキーマインスタンス名前空間に属している)にtrueを設定する。
<shipDate xsi:null="true"></shipDate>
null属性はXMLスキー
マインスタンス名前空間
(http://www.w3.org/1999/XMLSchema-instance)の一部として定
義されており、インスタンス文書中にはこの名前空間と関連つけられた接頭辞
(ここではxsi:)とともに出現しなければならない
(xsd:接頭辞と同様、xsi:という接頭辞も慣習と
して使われているだけである)。nullを扱う機構は要素の値にのみ適用され、
属性の値には適用されないことに注意。xsi:null="true"が付加された要素
は要素内容を持つことはできないが、属性を持つことはできる。
1つのスキーマは、型定義と要素宣言の集合(語彙)と
して捉えることができ、それらの型や要素の名前はある特定の名前空間に属し
ている。この名前空間のことを、対象名前空間(target namespace)と呼ぶ。対
象名前空間を使い分けることによって、ある語彙の定義・宣言を、異なる語彙
の定義・宣言から区別することができる。例えば、XMLスキーマ言語の語彙に
含まれるelement要素の宣言
と、ある仮想的な化学用言語の語彙に含まれるelement(元素)要
素のための宣言は、対象名前空間の違いによって区別できる。前者は、
http://www.w3.org/1999/XMLSchema対象名前空間の一部である
し、後者は別の対象名前空間の一部である。
(スキーマ妥当性検証と呼ばれる処理を通じて)あるイ ンスタンス文書が1個あるいはそれ以上のスキーマに適合しているかをチェッ クしたいときには、スキーマ中のどの要素および属性宣言と型定義が、インス タンス中の要素と属性をチェックするのに使われるべきかを同定する必要があ る。対象名前空間は、この同定処理において重要な役割を果たす。次節では、 対象名前空間のこのような役割について述べる。
要素や属性を同定する情報がインスタンス文書中でどう表現されるかは、 スキーマ設計者がいくつかの選択肢のどれを選ぶかによって影響される。具体 的には、設計者は、ローカルに宣言された要素や属性がインスタンス中で出現 するとき、名前空間によって修飾されなければならないかどうかを決める。修 飾の仕方は、明示的な接頭辞(prefix)によるものと、暗黙的なデフォルトによっ て修飾されるものの両方がある。ローカルな要素と属性の修飾に関するスキー マ作者の選択は、スキーマとインスタンス文書の構造に多くの影響を与えるも のであり、次節以降では、それらの影響のいくつかについて見てみる。
注文書スキーマの新しい版(po1.xsd) では、対象名前空間は明示的に宣言さ
れており、ローカルに定義された要素と属性は、修飾されない(unqualified)
と指定されている。po1.xsd中の対象
名前空間は、http://www.example.com/PO1 であり、targetNamespace 属性の値
として指定される。
ローカルな要素と属性の修飾は、schema要素のelementFormDefaultと
attributeFormDefault
の2つの属性によってそれぞれグローバルに定義される。あるいは、
form属性を使ってローカルな
宣言ごとに別々に指定することができる。これらの属性の値は、
unqualifiedあるいはqualifiedのどちらかであり、
ローカルに宣言された要素と属性が修飾されなればならないかどうかを表す。
po1.xsdでは、elementFormDefault と
attributeFormDefault
の両方に値としてqualifiedを設定することによって、要素と属
性をどう修飾するかがグローバルに定義されている。(訳
注 'unqualified'の間違いでは!')厳密に言えば、これは必要ではな
い。なぜなら、 qualifiedはこれらの属性のデフォルト値だか
らである。しかし、次節で述べる別の場合との対比を強調するために、この例
では明示している。
このスキーマの対象名前空間がどのように作られるかを知るために、型定
義と要素宣言をそれぞれ順にみていくことにしよう。スキーマの最後の方から
始める。最初に、name, streetなどから構成され
るAddressという型が定義されている。この型定義から言えるこ
との1つは、Address型がこのスキーマの対象名前空間に含まれ
るということである。次に、shipTo, billTo,
comment などから構成されるPurchaseOrderType
という型が定義されている。この型も、このスキーマの対象名前空間に含まれ
ている。ここで注意することは、3つの要素宣言において、型参照
po:Address, po:Address,
po:commentは修飾されていることである。また、接頭辞は名前
空間http://www.example.com/PO1に関連付けられている。これ
は対象名前空間と同じ名前空間であり、したがって、このスキーマのプロセッ
サが、Address型の定義および comment要素の宣
言を得るためには、このスキーマの中身を見ればいいことがわかる。異なる対
象名前空間を指定して、別のスキーマに含まれる型を参照することもでき、ス
キーマ間で定義と宣言の再利用ができる。
スキーマpo1.xsdの冒頭で、
purchaseOrderとcomment要素を宣言している。そ
れらは、このスキーマの対象名前空間に含まれている。
purchaseOrder要素の型は修飾されており、その理由は
Addressが修飾されているのと同じである。対照的に、
comment要素の型であるstringは修飾定されていない。 po1.xsdスキーマは、デフォルト名前空間の宣言
を含んでいるため、stringのような修
飾されていない型や、elementや complexTypeのような修飾されてい
ない要素は、デフォルト名前空間
http://www.w3.org/1999/XMLSchemaに関連付けられている。実
際、これはXMLスキーマそのものの対象名前空間であり、po1.xsdのプロセッサは、string型の定義や、element要素の宣言のために、XMLスキー
マにあるスキーマ(あるいはスキーマのスキーマとして知られている)の中身
を見ればよいことがわかる。
それでは、スキーマの対象名前空間が、適合するインスタンス文書にどの ような影響を与えるかについて調べてみよう。
上のインスタンス文書は、1つの名前空間
http://www.example.com/PO1を宣言し、apo:とい
う接頭辞と関連付けている。この接頭辞は、文書中の2つの要素、すなわち
purchaseOrderとcommentを修飾するのに用いられ
ている。この名前空間は、po1.xsd中
のスキーマの対象名前空間と同じであり、このインスタンス文書のプロセッサ
がpurchaseOrderとcommentの宣言を得るには、そ
のスキーマを見ればいいことがわかる。実際、対象名前空間という名前は、
purchaseOrder とcomment要素のための対象とな
る名前空間が存在するという意味から付けられている。したがって、スキーマ
中で指定された対象名前空間は、インスタンス中の対応する名前空間の検証を
制御する。
接頭辞apo:は、グローバルな要素
purchaseOrder とcommentに対して適用される。
さらに、elementFormDefaultと
attributeFormDefault
は、その接頭辞がshipTo, billTo,
name, streetのようなローカルに宣言された任意
の要素に対しては適用されないこと、任意の属性(すべてローカル
に宣言されている)についても適用されないことを要求する。
purchaseOrderおよびcommentは、グローバルな要
素である。これらはある特定の型の内容中ではなく、スキーマ全体の内容中で
宣言されているからである。例えば、purchaseOrderの宣言は、
po1.xsdのschema要素の子要素として現れている
が、shipTo要素の宣言は、Address型を定義して
いるcomplexType要素の子供と
して現れる。
ローカルな要素と属性を修飾することは必須ではないので、スキーマ妥当
なインスタンス文書を作成するために、スキーマの詳細に関する多少の知識が
インタンスの作者には必要となる。具体的に言うと、もし作者が、ルート要
素(purchaseOrderのような)だけがグローバルであることに確信
が持てるならば、ルート要素だけを限定することは簡単な話である。逆に、作
者は、すべての要素がグローバルに定義されていると知っていて、インスタン
ス文書のすべての要素を修飾する(たぶんデフォルト名前空間の恩恵にあずか
ることができる)かもしれない(3.3節 でこの
やり方を学ぶ)。一方、グローバルおよびローカルな宣言に一定のパターンがな
い場合、グローバルな要素(と属性)に正確に接頭辞をつけるためには、作者には、
スキーマに関する詳細な知識が要求される。
要素と属性は別々に修飾することができるが、まずはローカル要素の修飾
について考えよう。ローカルであるとスキーマ中で宣言されたすべての要素が
修飾されなければならないことを示すには、qualifiedを
elementFormDefault 属
性の値として設定する。
| 修飾されたローカル名に対応するためのpo1.xsdへの変更 |
<schema xmlns="http://www.w3.org/1999/XMLSchema"
xmlns:po="http://www.example.com/PO1"
targetNamespace="http://www.example.com/PO1"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<element name="purchaseOrder" type="po:PurchaseOrderType"/>
<element name="comment" type="string"/>
<complexType name="PurchaseOrderType">
<!-- etc -->
</complexType>
<!-- etc -->
</schema>
|
このスキーマに適合するインスタンス文書では、すべての要素は明示的に修飾される。
| 明示的に修飾されたローカル名を含む注文書 |
<?xml version="1.0"?>
<apo:purchaseOrder xmlns:apo="http://www.example.com/PO1"
orderDate="1999-10-20">
<apo:shipTo country="US">
<apo:name>Alice Smith</apo:name>
<apo:street>123 Maple Street</apo:street>
<!-- etc -->
</apo:shipTo>
<apo:billTo country="US">
<apo:name>Robert Smith</apo:name>
<apo:street>8 Oak Avenue</apo:street>
<!-- etc -->
</apo:billTo>
<apo:comment>Hurry, my lawn is going wild!</apo:comment>
<!-- etc -->
</apo:purchaseOrder>
|
別の方法として、各要素を明示的な修飾するかわりに、po2.xmlのように、デフォルト名前空間を使った暗黙的な修飾に置き換えてもよい。
po2.xmlでは、インスタンス文書中のすべての要 素が同じ名前空間に属している。この名前空間がデフォルトの名前空間として 宣言され、インスタンス文書中のすべての要素に適用されている。したがって、 どの要素も明示的に修飾する必要はない。修飾された要素のもう一つの例とし ては、 5章のスキーマがすべて修飾され た要素を使っている。
属性の修飾は要素の修飾と良く似ている。属性は、グローバルに宣言され
るか、または attributeFormDefault
がqualifiedにセットされた場合に修飾されねばならず、これら
はインスタンス文書中で接頭辞付きで現れる。修飾された属性の例として、2.9節で現れた、 xsi:null属性がある。実際、修飾さ
れるべき属性は、常に明示的に接頭辞で修飾されなければならない。なぜなら、
XML名前空間の仕様は
属性の名前空間についてのデフォルトの仕組みを提供しないからである。修飾
されることを要求されない属性は、インスタンス文書中で接頭辞なしで現れ、
多くの場合はそうなっている。
ここまで説明してきた修飾の仕組みは、特定の対象名
前空間の中のすべてのローカル要素とローカル属性を制御するものであった。
これを、各宣言毎にform属性
を使って制御することもできる。例えば、ローカルに宣言した属性
publicKeyをインスタンス文書において修飾しなければならない
ことを要求するには、次のように宣言すればよい。
| 1つの属性が修飾されていることを要求した例 |
<schema xmlns="http://www.w3.org/1999/XMLSchema"
xmlns:po="http://www.example.com/PO1"
targetNamespace="http://www.example.com/PO1"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<!-- etc -->
<element name="secure">
<complexType>
<!-- element declarations -->
<attribute name="publicKey" type="binary" form="qualified">
</complexType>
</element>
</schema> |
publicKey属性に関してだけは、 form属性の値がattributeFormDefault
属性の値に優先することに注意。form属性は、属性に対してだけでなく、
要素に関しても同様に適用することができる。上のスキーマに適合するインス
タンス文書の例を示す。
| 修飾された属性を持つインスタンス文書 |
<?xml version="1.0"?>
<purchaseOrder xmlns="http://www.example.com/PO1"
xmlns:po="http://www.example.com/PO1"
orderDate="1999-10-20">
<!-- etc -->
<secure po:publicKey="11110000111110100010">
<!-- etc -->
</secure>
</purchaseOrder>
|
名前空間中ですべての要素名が一意である場合、別なスキーマ作成のスタ
イルとして、すべての要素がグローバルであるようなスキーマを作ることもで
きる。これは、DTDにおいて<!ELEMENT>を使うのに似ている。下の例で
は、po1.xsdを変更し、すべての要素がグローバルに
宣言されるようにした。 elementFormDefault属性
と attributeFormDefault
属性は、グローバルな要素及び属性宣言しかないときには関係ないのでこの例
から除外した。
| すべての要素宣言をグローバルにした po1.xsd改変版 |
<schema xmlns="http://www.w3.org/1999/XMLSchema"
xmlns:po="http://www.example.com/PO1"
targetNamespace="http://www.example.com/PO1">
<element name="purchaseOrder" type="po:PurchaseOrderType"/>
<element name="shipTo" type="po:Address"/>
<element name="billTo" type="po:Address"/>
<element name="comment" type="string"/>
<element name="name" type="string"/>
<element name="street" type="string"/>
<complexType name="PurchaseOrderType">
<element ref="po:shipTo"/>
<element ref="po:billTo"/>
<element ref="po:comment" minOccurs="0"/>
<!-- etc -->
</complexType>
<complexType name="Address">
<element ref="po:name"/>
<element ref="po:street"/>
<!-- etc -->
</complexType>
<!-- etc -->
</schema>
|
この「グローバル版」のpo1.xsdで、インスタン ス文書 po2.xmlの妥当性を検証できるが、先にも述 べたように、このインスタンス文書は「修飾版」のpo1.xsdに対しても妥当である。別の言葉で言えば、ど ちらのスキーマ作成のアプローチでも、名前空間を指定しない同一の文書を妥 当性検証できる。したがって、ある意味ではどちらのアプローチも同様であるとい えるが、しかし、別の重要な観点からはこれらのアプローチは大きく異なる。 特に、すべての要素がグローバルに宣言されていると、ローカル名を利用する ことはできない。例えば、グローバルには"title"という要素を一つしか宣言 できない。ローカルに宣言すれば、"book"の子要素としては、 "title"要素を 文字列型として宣言し、また、同じスキーマ(同じ対象名前空間)において、別 の"title"要素を"Mr Mrs Ms"の列挙型として宣言することができる。
2節でXMLスキーマの基礎を説明したときには対象 名前空間を宣言しなかったし、インスタンス文書においても名前空間を宣言し なかった。それらの対象名前空間は何で、どのように参照されているのだろう か?
注文書スキーマpo.xsdで我々は対象
名前空間を宣言しなかった。また、スキーマ中で定義・宣言される型や要素を
参照するとき、対象名前空間とその接頭辞 (上で出てきたpo:な
ど)を関連付けることもしなかった。スキーマ中で対象名前空間を宣言し
なかった結果、このスキーマで定義または宣言されたもの、すなわち
AddressやpurchaseOrderなどは、名前空間につい
ての修飾なしで常に参照できるようになる。言い換えると、それらを参照する
際には、明示的な修飾による名前空間も、デフォルトによる暗黙的な名前空間
も必要としない。例えばpurchaseOrder要素は型参照
PurchaseOrderTypeを使っている。対照的に、XMLスキーマで決
めている要素または型であって、po.xsd
で使われているものは、XMLスキーマ名前空間に関連付けられている接
頭辞xsd:によって、すべて明示的に修飾されている。
対象名前空間のないスキーマにおける要素宣言は、インスタンス文書に現
れる、修飾されていない要素の妥当性を検証するのに用いられる。すなわち、
これらの要素宣言は、明示的な接頭辞あるいはデフォルト
(xmlns:) による名前空間修飾を持たない要素の妥当性を検証す
るために用いられる。したがって、名前空間を使わない、伝統的なXML 1.0の文書
を妥当性検証するには、対象名前空間のないスキーマを用いなければならない。
もちろん、名前空間を使わないXML 1.0文書は多く存在するので、対象名前空
間を指定しないスキーマは数多く書かれることになる。ある語彙を持つ文書の
妥当性を検証するには、その語彙に対応するスキーマ文書を(訳注 数多くのスキーマの中から)正しく選んでプロセサに
提示する必要がある。
2節で説明した注文書スキーマは、一つの文書に含まれ ており、スキーマに書かれた記述(要素宣言や型定義など)のほとんどは、ゼ ロから作られたものだった。実際には、スキーマの作者は、複数の文書に存在 する記述を利用してスキーマを構成し、既存の型に基づいて新しい型を生成し ようとするだろう。この節では、そのような構成と生成の仕組みについて述べ る。
スキーマが大きくなると、保守の容易さ、アクセス制御、可読性のために、
その内容を複数のスキーマ文書に分けることが多くの場合は望ましい。このため
に、住所に関する構成要素をpo.xsdか
ら抜き出し、 address.xsdという
名前の新しいファイルにおく。修正された注文書スキーマファイルをipo.xsdと呼ぶ。
住所に関する記述を含むファイルを以下に示す。
注文書と住所に関する様々な記述は、2つのスキーマファイルipo.xsd とaddress.xsdに書かれるように変わった。こ
れらの記述を、国際注文書スキーマの一部として取り込むために、言い換える
と国際注文書スキーマの名前空間に含めるために、ipo.xsdは include 要素を用いている。
<include schemaLocation="http://www.example.com/schemas/address.xsd"/>
このinclude要素が行うの
は、 address.xsdに含まれる定義
と宣言を取り込んで、国際注文書スキーマの対象名前空間の一部として利用可
能にすることである。includeを使うために特に注意すること
として、インクルードされる側の対象名前空間は、インクルードする側
の名前空間(この場合はhttp://www.example.com/IPO)と同じで
なければならない。
この例では、インクルードする側の文書が1つだけで、インクルードされ る側の文書も一つだけであった。実際には、複数のinclude要素を使って、1 個以上の文書をインクルードすることが可能である。また、他の文書をさらに インクルードする文書をインクルードすることが可能である。しかし、インク ルードの入れ子は、スキーマのインクルードされる部分が同じ対象名前空間で 定義されているときに限る。
複数のスキーマ文書にまたがって定義されるスキーマに、あるインスタン
ス文書が適合しているものとする。このインスタンス文書は、'最上位の'スキー
マ文書と共通の名前空間だけを参照すればよい。インクルードされた様々の
スキーマ文書にある定義をすべて一つにまとめるのは、プロセッサの責任であ
る。したがって、上の例では、インスタンス文書ipo.xml (4.3
節を見よ)は、共通の対象名前空間
http://www.example.com/IPOと, 1つのスキーマファイル
http://www.example.com/schemas/ipo.xsdだけを参照する(訳注 スキーマファイルは実際には参照されていない)。
address.xsd を得るのは、プ
ロセッサの責任である。
5.4節では、1つ以上の名前空間に属する内容を検 証するために、どのようにスキーマが使われるかを述べる。
住所について記述するため、まずAddressという複合型を通
常の方法で作成する(address.xsd
を見よ)。 Address型は、住所についての基本要素を含んでおり、
それらはname, street, cityであ
る。これを出発点に、新しい2つの複合型を派生型として定義する。これらは、
元々の型で定義されているすべての要素に加えて、アメリカとイギリスの住所
に特有の要素を含む。ここで用いられる、既存の型を拡張して新しい住所型
(複合型)を派生させるという技法は、2.5.1
節で使ったものと同じである。しかし、ここでの基底型が複合型であるの
に対し、以前の節では、基底型が単純型である点が異なる。
US-Address とUK-Addressという2つの新しい
複合型を作成する。作成には、complexType 要素、base属性、derivedBy属性を用いる。ある型を
拡張して複合型を作るとき、最終的に有効な内容モデルになるのは、基底型の
内容モデルに、拡張部分として記述された内容モデルを加えたものである。こ
の二つの内容モデルは、1つの順序付きグループの2つの子供として扱われる。
UK-Addressの場合、その内容モデルは、Address
の内容モデルにpostcode要素とexport-code属性
に関する宣言の内容モデルを加えたものである。これは、
UK-Addressを以下のようにゼロから作ることに相当する。
| 例 |
<complexType name="UK-Address">
<sequence>
<!-- content model of Address -->
<element name="name" type="string"/>
<element name="street" type="string"/>
<element name="city" type="string"/>
<!-- appended declarations -->
<element name="postcode" type="ipo:UK-Postcode"/>
<attribute name="export-code" type="positiveInteger"
use="fixed" value="1"/>
</sequence>
</complexType>
|
注文書は、顧客の注文に応じて生成されるものとし、送付先と請求先住所
が異なる国であると顧客は指定できるものとしよう。下に示す国際注文書
ipo.xmlは、商品がイギリスに送られ、
請求書はアメリカの住所に送られるという例を示している。もしも、国際注文
書のためのスキーマにおいて、請求先の国際住所と送付先の国際住所との可能な
組み合わせをすべて並べ上げなくても良いのなら、明らかにたいへん有効であ
る。さらに、Address型の新しい派生型を生成することで、国際
住所に関する新しい複合型を加えることが簡単にできるならば、さらに有効であ
る。
XMLスキーマでは、billTo と
shipToをAddress型として定義したのにもかかわ
らず、(ipo.xsdを見よ)、
Address型のインスタンスの代わりに国際住所のインスタンスを
使うことができる。言い換えると、その内容が UK-Address型に
適合するインスタンス文書は、文書中において Address型のイ
ンスタンスが期待されている場所に現れても妥当である
(UK-Addressの内容自体が妥当であることは仮定している)。
XMLスキーマのこの機能を利用するため、かつ、どの派生型を用いているのか
を正確に示すためには、インスタンス文書中で派生型を明示的に指定する必要
がある。派生型の明示的な指定は、XMLスキーマで規定するインスタンス用名
前空間(訳注 http://www.w3.org/1999/XMLSchema-instance
のこと)に属するxsi:type属性によって行われる。
上にあげたipo.xmlの例では、
UK-AddressおよびUS-Address派生型を使用してい
るということは、xsi:type 属性の値によって示され
ている。
4.7節では、 派生型によるこのような置き換えを禁止するための手法について述べる。
内容モデルを拡張することによって新しい複合型を派生することに加えて、 既存の型の内容モデルを制限することによって新しい型を派生することも可能 である。概念的には、複合型の制限は単純型の制限と同じであるが、複合型の 制限は、単純型の値の取り得る範囲ではなく、型の宣言である点が異なる。ま た、制限によって派生した複合型は、基底型によく似ているが、その宣言が、 基底型の対応する宣言をより制限するものである点が異なる。実際、新しい型 によって表現された値は、基底型によって表現された値の部分集合である。言 い換えると、基底型の値を想定したアプリケーションからみて、制限された型 の値は想定範囲内にある。
例えば、国際注文書にあるitemsのリストの定義を更新して、
注文中に少なくとも1個のitem を含むようにしたいと
思ったとしよう。 ipo.xsdに示すスキー
マは、itemという子要素が1個も出現しない
itemsが許されている。新しい型ConfirmedItems
を作成するためには、新しい型を通常の方法で定義し、それが
Itemsという基底型から派生したものであると指定し、新しい型
が制限によって派生したものであると指定し、item 要素が出現
する回数の新しい(より制限された)最小値を与える。
| Itemsから、制限によってConfirmedItemsを派生する |
<complexType name="ConfirmedItems"
base="ipo:Items" derivedBy="restriction">
<!-- item element is different than in Items-->
<element name="item" minOccurs="1" maxOccurs="unbounded">
<!-- remainder of definition is same as Items -->
<complexType>
<element name="productName" type="string"/>
<element name="quantity">
<simpleType base="positiveInteger">
<maxExclusive value="100"/>
</simpleType>
</element>
<element name="price" type="decimal"/>
<element ref="ipo:comment" minOccurs="0"/>
<element name="shipDate" type="date" minOccurs='0'/>
<attribute name="partNum" type="ipo:Sku"/>
</complexType>
</element>
</complexType>
|
0個以上の子要素を許すのではなく1個以上の要素を要求するという変更は、
子要素の許される値の最少限を0から1に制限する。注意すべき点は、すべての
ConfirmedItems型の要素は、 Item型の要素とし
ても許容されるということである。
制限による派生をさらに説明するために、型定義に含まれる要素宣言と属 性宣言がどのように制限されるかの例を表3 にいくつか示す(この表は要素に関する構文を示しているが、最初の3つの 例は属性についての制限としても妥当なものである。)
| 表3. 制限の例 | ||
|---|---|---|
| 基底 | 制限 | 注 |
| default="1" | 元々何も定義されていない状態でデフォルト値を指定する | |
| fixed="100" | 元々何も定義されていない状態で固定値を指定する | |
| type="string" | 元々何も定義されていない状態で型を指定する | |
| (minOccurs, maxOccurs) | (minOccurs, maxOccurs) | |
| (0, 1) | (0, 0) | オプショナルな構成要素の削除 |
| (0, unbounded) | (0, 0) (0, 37) | |
| (1, 9) | (1, 8) (2, 9) (4, 7) (3, 3) | |
| (1, unbounded) | (1, 12) (3, unbounded) (6, 6) | |
| (1, 1) | - | minOccursもmaxOccursも制限できない |
XMLスキーマは、ある要素を別の要素で置き換えるため
の仕組みを持っており、同値クラス(equivalence classes)と呼ばれている。
具体的には、要素をある特別な要素クラスに割り当てることによって、雛型
(exemplar)という、名前付きの特定の要素と同値であることを示すことができ
る。雛型は、グローバルな要素でなければならないことに注意してほしい。例
えば、 customerComment およびshipComment と
いう要素を定義し、雛型がcomment であるような同値クラスに
割り当てることができる。その結果、customerCommentと
shipCommentは、 commentが使える任意の場所で
用いることが可能になる。等価クラスに含まれる要素は雛型と同じ型を持つか、
雛型の型から派生されたものでなければならない。これら2つの新しい要素を
宣言し、comment要素と同値なものにするには、以下のような構
文を用いる。
| commentと同値な要素を宣言する |
<element name='shipComment' type='string' equivClass='ipo:comment' /> <element name='customerComment' type='string' equivClass='ipo:comment' /> |
これらの宣言を国際注文書スキーマに追加すると、 インスタンス文書中に
あるcommentの置き換えが可能になる。例を下に示す。
| ipo.xmlの一部で要素の置換えを行なう |
....
<items>
<item partNum="833-AA">
<productName>Lapis necklace</productName>
<quantity>1</quantity>
<price>99.95</price>
<ipo:shipComment>Use gold wrap if possible</ipo:shipComment>
<ipo:customerComment>
Want this for the holidays!
</ipo:customerComment>
<shipDate>1999-12-05</shipDate>
</item>
</items>
....
|
同値クラスが存在しても、そのクラスに含まれる要素のどれかを使うことが必須になるわけではなく、雛型の使用を妨げるものでもない。単に、相互に交換できる要素を許すための仕組みを提供している。
XMLスキーマは、ある特定の要素や型を置き換える
(substitution)ことを強制するための仕組みを持っている。"抽象的
(abstract)"であると宣言されたた要素や型は、インスタンス文書で使用でき
ない。ある要素が抽象的であると宣言されたとき、その要素の同値クラスのメ
ンバがインスタンス文書中に現れなければならない。また、ある要素に対応す
る型が抽象的であると定義された場合、その要素のすべてのインスタンスは、
それが抽象的でない派生型であることを示すために xsi:typeを用いなければならない。
4.5節で示した同値クラスの例において、
comment要素を使うことを明確に禁止し、インスタンスでは
customerCommentおよび shipCommentを使わなけ
ればならないと指定したいとしよう。Commentが抽象的であると
宣言するには、国際注文書スキーマipo.xsdの元々の宣言を次のように修正する。
<element name="comment" type="string" abstract="true"/>
commentが抽象的であると宣言されているので、もはや国際
注文書のインスタンスは、customerCommentと
shipComment要素を含むときにのみ妥当である。
要素を抽象的であると宣言したときには、同値クラスを使わなければなら
ない。それに対して、型を抽象的であると定義したときには、インスタンス文
書中でそれから派生する型( xsi:type 属性で同定される)を使
うことが単に要求される。次のスキーマ定義を考えてみよう。
| 乗り物用のスキーマ |
<schema xmlns='http://www.w3.org/1999/XMLSchema' targetNamespace='http://cars.example.com/schema' xmlns:target='http://cars.example.com/schema'> <complexType name='Vehicle' abstract='true'/> <complexType name='Car' base='target:Vehicle' /> <complexType name='Plane' base='target:Vehicle' /> <element name='transport' type='target:Vehicle' /> </schema> |
transport要素は、抽象的ではないので、インスタンス文書中に現れることができる。しかし、その型定義は抽象的なので、派生型を参照するxsi:type属性なしにインスタンス文書中に出現することはない。つまり、以下のものはスキーマ妥当(schema-valid)でない。
<transport xmlns="http://cars.example.com/schema" />
なぜなら、transport要素の型が抽象的だからである。しかし次のものはスキーマ妥当である。
<transport xmlns="http://cars.example.com/schema"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xsi:type="Car"/>
|
なぜなら、Vehicleと置き換え可能であって、抽象的でない
型(訳注 Carのこと)を使っているからである。
これまでは、新しい型を派生し、それをインスタンス
文書中で制限なしに使うことができた。実際には、スキーマの作者は、ある特
定の型からの派生型を禁止し、インスタンス中で派生型を使うことを禁止した
いと思うことがあるだろう。たぶん、もっとも簡単な制限の形式は、ある特定
の型(単純型あるいは複合型)に対し、新しい型が、(a) 制限によって、(b) 拡
張によって、(c) どちらの場合でも、派生できないと指定することである。例
として、制限による Address型の派生を抑制する場合を考えて
みる。Address型は、拡張によってUS-Addressお
よびUK-Addressのような型を定義するための基底としてだけ使
いたいからである。このようなすべての派生を抑制するためには、元の
Address型の定義を以下のように修正するだけである。
| Addressの制限による派生を禁止する |
<complexType name="Address" final="restriction"> <element name="name" type="string"/> <element name="street" type="string"/> <element name="city" type="string"/> </complexType> |
final属性の
restriction という値は、制限による派生を禁止する。すべての派生を禁止する、あるいは拡張による派生を禁止するには、それぞれ
#allと extensionを指定する。schema要素は省略可能な
finalDefault属性を持ち、その値はfinal属性に許される値のうちの1つである。finalDefault属性の効果は、final属性をスキーマ中のすべての要素宣言で指定するのと等価である。
派生と同値クラスをインスタンス文書中で使ってもよ
いかどうかを制御する別の仕組みがある。4.3節では、派生型
US-AddressとUK-Addressが、インスタンス文書中
のshipToとbillToでどのように使われるかについ
て述べた。これら2つの派生型は、Address型によって与えられ
る内容モデルを置き換えることが可能である。なぜなら、これらの型は
Address型の派生型だからである。しかし、派生型による置き換
えは、型定義中のblock属性
によって制御することが可能である。例えば、もし Addressの
場所でのすべての制限による派生を阻止(block)したいならば(おそらく、
final='restriction'属性を
使ってAddress型を定義したのと同じ理由で)、
Address型の元々の定義を以下のように修正する。
| インスタンス中でのAddressの制限による派生の抑制 |
<complexType name="Address" block="restriction"> <element name="name" type="string"/> <element name="street" type="string"/> <element name="city" type="string"/> </complexType> |
block属性の
restrictionという値は、インスタンス中で、制限による派生が
Address型を置き換えるのを抑制する。しかし、
UK-AddressとUS-Address型が
Address型を置き換えるのは抑制しない。何故なら、それらは拡
張による派生だからである。すべての派生による置き換えを抑制するには値
#allを指定し、拡張による派生の置き換えを抑制するには値
extensionを指定する。 finalと同様に、 schema要素は省略可能な
finalDefault属性を持つことができ、その値はfinal属性に許される値のうちの1つで
ある。finalDefault属性の効果は、final属性をスキーマ中のすべての要素宣
言で指定するのと等価である。(訳注 この段落の
finalDefault属性はblockDefaultに、
final属性はblockに置き換えるべきでは?)
家庭用品の注文と請求をするアプリケーションが、地域毎にどんな種類の
製品がどれだけ請求されたかをまとめた特別レポートを生成するとしよう。こ
のようなレポートの例として、1999年の第4四半期のものを、4Q99.xmlに示す。
この節では、スキーマ中では修飾された要素(qualified element)を、また、 インスタンス中では可能な限りデフォルト名前空間を使うことにする。
このレポートは、各郵便番号について、その地域で請求された製品番号と 数量をリストし、製品について短く記述する。請求データをまとめるとき、レ ポートの意図が明快で、データに曖昧さがないのは、多くの制約(constraint) を用いているためである。例えば、各郵便番号はそれぞれ1回しか現れない (一意性の制約)。また、注文のあった各製品は、いくつかの郵便番号に請求 されていても、一度しか記述されない(参照の制約)。例えば、製品番号 455-BXを見よ。次節以降で、これらの制約を XMLスキーマ中で使う方法を述べ る。
XMLスキーマでは、任意の属性あるいは要素の値が特定
のスコープで一意(unique)であると指定できる。ある属性あるいは要素の値が
一意であることを指定するには、unique要素を使って要素の集合を選び出
し、選び出された要素集合の中で一意になるのがどの属性または要素であるか
を指定する。我々のレポートスキーマreport.xsdの場合は、selector要素が
regions/zipというXPath表現(XML Path Language 1.0を見よ) を
用いてすべてのzip要素をレポート文書から選び出す。次に、
field要素が、もう一つのXPath
表現@codeを使って、選び出された要素の中でcode属性
が一意でなければならないことを指定する。レポート文書が、これら2つの
XPath表現で指定されたスコープの外にcode属性を持っているか
もしれないが、これらは一意である必要はない。
さらに、我々はフィールドの組が一意であることを指定できる。例えば、
一つの郵便番号についてのリストは一回だけであるという制約は緩めるが、ど
の製品も各郵便番号に対して1回しか現れてはいけないという制約を代わりに
導入するものとする。この制約は、郵便番号と製品番号の組が一意でなければ
ならないという指定をすることで表現できる。上記の四半期レポート文書
4Q99.xml では、{95819 872-AA}、
{95819 926-AA}、{95819 833-AA}、{95819 455-BX}、{63143 455-BX}が、可能
な組み合わせである。明らかに、郵便番号と製品番号の組み合わせを考えても、
一つの郵便番号に対して一つのリストに含まれているのか、一つの郵便番号に
対して複数のリストに含まれているのかを区別できない。しかし、これらの組
み合わせは、ある一つの郵便番号の中に現れた製品を表している。言い
換えると、この一意性の制約を犯した場合は、スキーマプロセサによって発見
される。
値の組み合わせを定義するには、組み合わせたいすべての値について、そ
れを指定するfield要素
を加えるだけでよい。したがって、部品番号を先の定義に加えるには、新たな
field要素を追加し、
part 要素(regions/zipで指される
zipの子要素)のnumber属性を指す、
XPath 表現part[@number]をその値とすればよい。
| A Unique Composed Value |
<unique> <selector>regions/zip</selector> <field>@code</field> <field>part[@number]</field> </unique> |
上記の四半期レポートでは、各製品の記述はそれぞれ1
回しか現れない。この制約は、uniqueを使って表現できた。しかし、さ
らに加えて、どの郵便番号の下に現れるどの製品-数量要素に関しても、
対応する製品記述が必ず存在するようにしたい。この制約は、key要素とkeyref要素を用いて表すことができる。
四半期レポートのスキーマreport.xsdでは、key要素及びkeyref要素が、unique要素とほぼ同じ構文で用いられること
を示している。key要素は、
parts要素の子要素であるpart要素の
number属性に関して適用される。numberがキーで
あるという宣言の意味は、この値が一意であって、null値であってはならず、こ
のキーにつけられた名前pNumKeyによってこのキーが他から参照
可能なことを示している。
製品-数量要素が、対応する製品記述を持つことを保証するためには、これ
らの要素
(<selector>regions/zip/part</selector>)の
number属性(
<field>@number</field>) が、
pNumKeyというキーを参照することを指定すればよい。
number属性がkeyrefであるというこの宣言は、この値が一意で
あることは要求しないが、この値を持つpNumKey が存在するこ
とを要求する。
unique要素の場合と同様に、
keyやkeyrefに値の組み合わせを指定すること
もできる。この仕組みを使えば、製品番号など単純な値の一致だけでなく、値
の組み合わせがキーとして一致することを要求できる。このような値の組み合
わせとしては、複数の型(string、
integer、date, など)を許すことも field要素の順序と型が key定義と keyref定義の双方で一致している限り、
可能である。
XML 1.0では、属性型ID, IDREF, IDREFSを用いて、属性の値の一意性を保
証することができた。この仕組みは、XMLスキーマにおいても、単純型