要素宣言は、XMLで使用するタグの定義です。
XMLスキーマの中で、要素(element)として宣言すると、XMLデータの中で「タグ」として使うことができるようになります。
要素宣言では、要素の名前(name)と要素の型(type)を指定します。要素宣言で指定された名前がタグとして、また、型で指定した内容がタグに囲まれたデータとしてXMLデータに出現します。図2-1の例では、要素の名前に「建物名」を指定し、要素の型には「xs:string(文字列)」を指定しています。
図 2‑1 要素宣言
なお、「xs:string」の前についている「xs」と「xs:element」の前についている「xs」は、これらの名前がW3Cの名前空間で定められた要素であることを示す接頭辞(1.4節参照)です。
図2-1のXMLスキーマの例に従って作成したXMLデータの例を図2-2に示しますと、<ex:建物名>という開始タグと</ex:建物名>という終了タグがXMLデータに出現し、これらの開始タグと終了タグに囲まれた値は、文字列となります。
図 2‑2 XMLデータの例
要素の名前には、任意の文字列を指定できます。ただし、「?」(疑問符)や「!」(感嘆符)等の記号は使用できない、1文字目に数字を使用することができないといったルールがあります。
また、日本語(全角の平仮名、漢字、カタカナ)でも構いませんが、文字化け等の不具合を考慮し、半角のアルファベットが使用されることが一般的です。アルファベットは、大文字と小文字が区別されますので、<ex:BuildingName>と</ex:buildingName>は開始タグと終了タグの不一致(エラー)となることに注意してください。
※ただし、このチュートリアルでは、見た目のわかりやすさを考慮し、日本語のタグを使って解説しています。
要素の型には、文字列(xs:string)や整数(xs:integer)のような単純な型だけではなく、複数の要素のまとまりのような複合的な型を指定できます。この単純な型や複合的な型は、XMLスキーマの中で自由に定義することもできます。定義の方法は、以降の節で説明します。
ポイント: 要素宣言は、XMLで使用可能なタグの宣言です。
要素の内容となる「型」を定義することを、「型宣言」といいます。宣言できる型には、文字列(string)や整数(integer)のような単純な値をとる、単純型(simpleType)と、複数の要素のまとまりとなる複合型(complexType)があります。
「単純型」は、要素の内容が文字列や数値、日付のような単純なデータの型を指します。
XMLスキーマでは、文字列型、整数型、日付型のように、よく利用されるデータの型が「組み込みデータ型」としてあらかじめ定義されています(表2-1)。また、新たな「単純型」を作成することもできます。これは組み込みデータ型である単純型をベースに作成します。詳細は、2‑1節で説明します。
表 2‑1 よく使われる単純型
※xs:は接頭辞
ポイント: 文字列や数値、日付等の単純なデータの型を単純型と言います。
「複合型」は、要素の内容が、複数の要素等となるデータの型を指します。
複合型宣言は「complexType」という要素を使って宣言します。複合型の名前(name)を指定するとともに、「complexType」の子要素として「sequence」を記述し、さらにその内容として要素宣言を列挙します。
図2-3に、複合型宣言の例を示します。
図 2‑3 複合型宣言
この例では、「建物type」という名前の複合型を定義し、その内容として「建物名」、「用途」、「地上階数」及び「地下階数」のそれぞれ要素宣言を記述しています。
ここで、「sequence」は順列という意味を持ちます。「sequence」のタグに囲まれた要素は、XMLスキーマで記述された順序と、XMLデータでタグとして出現する順序が一致しなければなりません。
図2-3の例の場合、XMLデータには「建物名」、「用途」、「地上階数」及び「地下階数」の順序でタグが出現しなければなりません。
宣言した複合型は、要素宣言の中で、要素の型(type)として使用します(図2-4)。
図 2‑4 要素宣言での複合型の指定
図2-4に示した要素宣言では、「建物」というタグが宣言され、<建物>と</建物>の間に含まれるべき内容は、「建物type」であると定義しています。「建物type」の前に、「ex:」という文字列が付いていますが、これは「建物type」という複合型が定義されたXMLスキーマを明確にするための接頭辞です。接頭辞は、宣言(name=“○○”)ではつきませんが、要素の型として使用する場合のように、それが使用される場所では接頭辞が付きます。接頭辞の詳細は2.3節で説明します。
さて、図2-3で示した「建物type」のXMLスキーマによると、「建物type」には、4つの要素宣言が含まれています。「sequence」で囲まれていますので、XMLスキーマで記述された順序と同じ順序でタグが出現します。
このXMLスキーマに従って作成されたXMLデータの例を 図2-5に示します。
図2-5 XMLデータの例
「建物」の開始タグと終了タグの間に、「建物名」、「用途」、「地上階数」及び「地下階数」の4つのタグが出現しており、これはXMLスキーマで記述された順序に一致します。また、タグに囲まれる内容は、「建物名」と「用途」は文字列、「地上階数」と「地下階数」は整数になっています。
なお、タグになるのは要素宣言だけですので、複合型の名前(図2-3の例では「建物type」)がタグとして出現することはありません。
このように、複合型宣言を使うと、タグの入れ子構造を作成できます。複合型の中に定義される要素宣言の型を複合型にすることで、入れ子構造の階層はさらに深くなります。
ポイント: 要素のまとまりとなるデータの型を複合型と言います。複合型の中で「sequence」のタグに囲まれた要素は、XMLスキーマで記述された順序とXMLデータでタグとして出現する順序が一致しなければなりません。
複合型宣言では、複合型に含める要素の多重度を設定できます。多重度とは、その要素を繰り返し記述できる回数です。
多重度は、下限(minOccurs)と上限(maxOccurs)をそれぞれ指定します(表2-2)。下限と上限は、minOccurs=”0” maxOccurs=”1”のように数字で指定します。上限を設けない場合は、数字の代わりに「unbounded」と記載します。また、下限及び上限の指定が省略された場合は1回であることを意味します。
表 2‑2 多重度の記法
図2-6に多重度を設定した複合型「建物type」と、これを型として持つ要素「建物」のXMLスキーマを示します。
図 2‑6 多重度の記述例
「建物type」に含まれる要素宣言の多重度を見てみましょう(表2-3)。
表 2‑3 要素が出現可能な回数
「建物名」の多重度は、「minOccurs=”0” maxOccurs=”2”」です。下限は0で上限は2となります。つまり、「建物名」のタグは省略してもよいし、記述する場合は、最大2回記述できます。「用途」の多重度は「maxOccurs=”unbounded”」です。この場合、下限は省略されているので1、つまり、「用途」のタグは必ず1回記述しなければなりません。一方、上限は「unbounded」ですので、何回でも「用途」のタグを記述することができます。「地上階数」は多重度が省略されていますので、必ず1回記述します。「地下階数」は「minOccurs=”0”」です。下限が0となっていますので、タグは省略可能です。上限は省略されているので1、つまり、記述する場合は1回のみです。
このXMLスキーマに従ったXMLデータの例を図2-7に示します。
図 2‑7 XMLデータの例
1つ目の例(建物名が「中央合同庁舎3号館」)には、4つの要素がそれぞれ1度ずつ出現しています。2つ目の例(建物名が「A駅前ビルディング」、「駅ビル」)には、「建物名」が2回、「用途」が3回、地上階数は「1回」出現し、「地下階数」は記述されていません。これら2つのXMLデータでの各要素の出現回数は、XMLスキーマで指定された多重度の範囲内です。いずれもXMLスキーマに対して妥当なXMLデータとなります。
XMLデータの記述で注意が必要な点は、多重度に従い複数回要素を記述する場合も、必ずXMLスキーマで指定された順序で出現することです。
図2-8にエラーとなる例を示します。
図 2‑8 エラーとなるXMLデータの例
図2-8では、<用途>のタグの後に<建物名>のタグが出現しています。図2-6の通り、XMLスキーマでは、<用途>は<建物名>の後に出現することになっていますので、この例は、XMLスキーマに適合していない、妥当ではないXMLデータです。
ポイント: 複合型宣言では、多重度で要素の出現回数を指定できます。
XMLスキーマでは要素や型を定義しますが、名前空間を使って定義した要素や型を識別するには、名前空間と、名前空間に対する接頭辞を指定しなければなりません。名前空間とは、要素や型の名前の集合となる概念です(1.4節参照)。
名前空間と接頭辞を指定する例を図2-9に示します。名前空間と接頭辞の指定は、schemaタグの属性を用います。schemaタグは、これがXMLスキーマであることを示すタグです。
図 2‑9 名前空間と接頭辞の例
XMLスキーマで定義する要素や型が含まれるべき名前空間の指定は、targetNamespace属性を使用します。値として、名前空間のURIを記述します。
また、XMLスキーマの中で使用する要素や型が含まれる名前空間を識別するためには、xmlns属性を使用します。xmlns属性にも値として名前空間のURIを記述します。xmlns属性は、一つ一つの要素や型に指定することができますが、その場合は、XMLスキーマの記述が冗長になります。そこで、通常は、図2-9の例のように、schemaタグにおいて、接頭辞を指定し、以降は要素や型の名前に接頭辞を付けることで識別できるようになっています。xmlns属性における接頭辞の指定は、xmlnsのあとにコロン(:)をはさんで接頭辞を記述し、値としてその接頭辞に対応する名前空間のURIを記述します。
図2-9の例では、名前空間として「http://sample.org/schemas/ex」を指定し、その接頭辞として、「ex」を指定しています。また、もう1つ接頭辞として、「xs」を指定しており、その名前空間は、「http://www.w3.org/2001/XMLSchema」です。これは、W3CがXMLスキーマの定義に必要な要素等を定義した名前空間です。この名前空間で定義された要素等を使用する場合には、xsという接頭辞が付けられることになります。実際に、この例の中では「schema」タグに接頭辞xsが付けられ、「xs:schema」と記述されています。この接頭辞があることで、「schema」タグが、W3Cで定義されたXMLスキーマの定義のためのタグであることがわかります。
次節で説明しますが、名前空間と接頭辞を使うことで、他で定義された要素や型を利用することができます。
ポイント: XMLスキーマでは、定義する要素や型の名前空間と接頭辞を指定します。
なお、XMLスキーマでは、「デフォルトの名前空間」という、接頭辞を使用しない名前空間を宣言する方法もあります。ただし、接頭辞が付いていないと、どの名前空間に属する要素なのかがわかりづらくなってしまいます。3D都市モデルでは、複数の名前空間で定義されている要素を使用している都合上、接頭辞は省略せず、全ての要素に接頭辞を付けることにしています。そのため、このチュートリアルでも、接頭辞を省略する方法の説明は割愛します。
XMLスキーマを作成する際に、他のXMLスキーマで定義された要素等を再利用することができます。このときに、名前空間と接頭辞を使って、他のXMLスキーマで定義された要素等を識別します。XMLスキーマを再利用する仕組みには、異なる名前空間の要素や型を再利用する仕組みと、同じ名前空間の要素や型を再利用する仕組みの2つがあります。
「import」は、異なる名前空間で定義された要素等を利用する場合に使用します。「import」の仕組みを図2-10に示します。
図 2‑10 importの仕組み
「import」では、再利用したい要素等が定義された名前空間のURIと、利用したい要素等の定義が含まれるXMLスキーマファイルの物理的な所在を指定します。名前空間は、namespace属性で指定し、要素等が定義されたXMLスキーマファイルの位置は、schemaLocation属性で指定します。
具体的な記述例を図2-11に示します。
図 2‑11 importの記述
ここでは、CityGMLに定義された要素等を呼び出しています。
namespace属性に名前空間である「http://www.opengis.net/citygml/building/2.0」を指定し、schemaLocationにファイルの所在である「http://schemas.opengis.net/citygml/2.0/cityGMLBase.xsd」を指定しています。
図2-11の例を見ていただくとわかるように、名前空間のURIとファイルの所在となるURIはまったく別のものでもかまいません。名前空間のURIはあくまで名前を識別するための概念であり、schemaLocationは、ファイルがある具体的な場所になります。
なお、importした名前空間に対応する接頭辞もXMLスキーマの中で宣言しなければなりません。また、XMLスキーマを定義するために必要となる要素や型が定義されたW3Cの名前空間については、import文の記載は不要ですが、接頭辞は指定しなければなりません。
ポイント: importは、異なる名前空間の要素や型を再利用したい場合に使用します。
「include」は、同じ名前空間で定義された要素等を利用する場合に使用します。「include」の仕組みを図2-12に示します。
図 2‑12 includeの仕組み
再利用したい要素等が定義された名前空間は同じですので、その要素等が定義されたXMLスキーマファイルの物理的な位置のみを指定します。この指定には、schemaLocation属性を用います。
具体的な記述例を図2-13に示します。schemaLocationにファイルの所在である「http://sample.org/schemas/sample2.xsd」を指定しています。
図 2‑13 includeの記述
includeは、同じ名前空間でなければ使用することができません。同じ名前空間ですので、includeするXMLスキーマと、includeされるXMLスキーマには、同じ名前の要素や型が含まれていてはなりません。
ポイント: includeは、同じ名前空間の要素や型を再利用したい場合に使用します。
XMLスキーマでは、すでに定義された型をベースに、新しい型を定義できます。これを「派生」と言います。派生には、制限(restriction)と拡張(extension)があります。制限は、既に定義されている型が許す範囲を狭める(制約を強める)ことであり、拡張は既に定義されている型が許す範囲を広げる(制約を緩める)ことです。
型の制限は、既にある「単純型」をベースに、新たな「単純型」を作成するときに使用します。制限は、restrictionというタグを使用して定義します。また、元となる単純型をbase属性により指定し、具体的に制限する内容を記述します。
例えば、xs:stringは文字列型であり、その値として、どんな文字列でも記述できます。これに対して、restrictionを使用することで、特定の文字列しか記述できないように制限することができます。図2-14に例を示します。
図 2‑14 単純型の制限の記述例
この例では、建物の「用途」として、「官公庁施設」、「官公庁施設以外」及び「不明」という3つの値のいずれかしか記述できないように制限しています。
新しく定義した単純型(simpleType)である「建物用途」は、元になる単純型として文字列(xs:string)を指定し、これを制限(restriction)して、記述可能とする値(官公庁施設、官公庁施設以外、不明)を列挙(enumeration)しています。
restrictionでは、元となる単純型を制限する範囲を指定できますが、その指定の方法として、上述のようにとりうる値を指定する方法の他に、使用可能な文字を指定する方法、文字数の上限や下限を指定する方法等があります。
ポイント: 単純型を制限することで、使用可能な値の範囲を狭める新たな単純型を作成することができます。
型の拡張は、既にある「複合型」をベースに、新たな「複合型」を作成するときに使用します。
拡張では、既にある複合型に、要素を追加できます。拡張は、extensionというタグを使用して定義します。また、元となる複合型をbase属性により指定します。図2-15に複合型の拡張の例を示します。
図 2‑15 複合型の拡張の記述例
ここでは、複合型である「建物type」を拡張し、新たに「マンションtype」という複合型を定義しています。このとき、マンションtypeには「戸数」という要素を追加しています。
なお、extensionを使って複合型を拡張する場合は、その内容が複合型であることを示すcomplexContentというタグを一緒に使用することがXMLスキーマのルールとして決まっています。
複合型「建物type」とそれを拡張した「マンションtype」を型として指定した要素を宣言し、その要素に従って作成したXMLデータの例を見てみましょう。図2-16に要素宣言と、その要素宣言に従って作成したXMLデータを示します。
図 2‑16 複合型の拡張を使用した場合のXMLデータの例
「建物」のデータには、子要素として「建物名」、「用途」、「地上階数」及び「地下階数」というタグが出現しています。一方、「マンション」のデータには、これら4つのタグに加えて、「戸数」というタグが追加されています。
このように、拡張の仕組みを使うと、既にある複合型に要素を追加できます。
拡張により作成した複合型をさらに拡張して、新しい複合型を作成することもできます。この場合、拡張により追加された要素は後ろに追加されていくことに注意してください。
例えば、「マンションtype」を拡張して「賃貸マンションtype」を作成したとします(図2-17)。この複合型を型として持つ要素のXMLデータを作成した場合、まず、「建物type」で定義した要素がタグとして出現し、次に、「マンションtype」で定義した要素がタグとして出現します。最後に、「賃貸マンションtype」で定義した要素がタグとして出現します。
図 2‑17 複合型をさらに拡張した例
ポイント: 複合型を拡張することで、要素を追加する新たな複合型を作成することができます。
XMLの属性は、要素への付加的な情報です。
XMLの属性は、「attribute」タグを使用して定義します(図2-18)。
図 2‑18 属性宣言
name属性により、属性の名前を指定します。また、type属性により、属性の型を指定します。use属性は、属性の省略可否を指定します。属性の型は、単純型のみ指定可能です。属性の省略可否は、「required」の場合は必須(必ず1つ記述する)、「optional」の場合は省略可となります。
XMLの属性は、その型として単純型のみを指定できます。複合型は指定できません。
属性宣言は、要素の型となる型宣言(単純型又は複合型)の中で記述します(図2-19)。
属性宣言の結果は、要素の開始タグの中に、「属性の名前=”属性の型で指定された種類の値”」というように出現します。
図 2‑19 型宣言の中に記述する属性宣言
ポイント: XMLの属性は要素の付加的な情報ですが、単純型のみ指定することができ、結果は開始タグの中に記述されることになります。
代替グループ(substitutionGroup)は、ある要素の代わりに、他の要素を使用することを許可する仕組みです。代替グループは、要素宣言の中で、substitutionGroup属性を使って、定義済みの要素を指定します。substitutionGroup=”○○”という記載のある要素は、○○という要素の代わりに使用できることを意味します。
図2-20に例を示します。ここでは、「マンション」の要素宣言の中で、この要素は、「建物」という定義済みの要素の代わりに使用することができる、と宣言しています。
図 2‑20 代替グループの指定
代替グループを使って、定義済みの要素の代わりに使用する例を図2-21に示します。
図 2‑21 要素の参照
この例では、先ほどと同様、「マンション」が「建物」の代わりに使えると宣言しています。さらに、「自宅」という要素が宣言されており、「自宅」の型である「自宅type」では、「建物」という要素を呼び出して(ref)います。この呼び出しは、定義済みの要素を使用することを意味します。
このXMLスキーマに従った「自宅」のXMLデータの例を図2-22に示します。
図 2‑22 参照された要素を含むXMLデータの例
「自宅type」では、「建物」という要素を呼び出しています。そのため、「自宅」の子要素として、「建物」のデータが記述されることになります。「建物」のXMLスキーマは、図 2‑6を参照してください。
もう1つ例を見てみましょう(図2-23)。
図 2‑23 代替グループの要素を含むXMLデータの例
代替グループの指定により、「マンション」は「建物」の代わりに使用できます。よって、「自宅」の子要素として「マンション」を記述できます。
ポイント: 代替グループが指定された要素は、指定された要素の代わりに出現することができます。
これまでで、XMLスキーマを構成する様々な記法を説明しました。これらの記法に従って、XMLスキーマは1つのファイルとして記述されます。
XMLスキーマの全体構成を図2-24に示します。
図 2‑24 XMLスキーマの全体構成
XMLスキーマもXMLであるため、最初にこのファイルがXMLであることを宣言します。次に、このファイルが、XMLスキーマであることを、「schema」要素を使用して宣言します。この「schema」要素の開始タグの中で、名前空間や使用する接頭辞を指定します。次に、必要に応じて、他のXMLスキーマで定義された要素や型を再利用したい場合は、importやincludeを使用してその名前空間やファイルの場所を指定します。そして、要素宣言や型宣言により、要素や型を定義します。最後に、「schema」要素の終了タグを記載して、XMLスキーマは完成します。
ここで、XMLスキーマでの要素や型、属性の宣言には、「グローバル宣言」と「ローカル宣言」の区別があります。
l グローバル宣言:schemaタグの直下にある、要素、型及び属性の定義。他のXMLスキーマから参照(2.7節参照)することができます。
l ローカル宣言:複合型の宣言の中で定義されている要素のように、schemaタグの直下ではない場所での要素、属性及び型の定義。他のXMLスキーマから参照することができません。