2.5. 複雑なデータ型の定義

概要

XML スキーマは、単純なデータ型から複雑なデータ構造を構築するための柔軟で強力なメカニズムを提供します。要素と属性のシーケンスを作成することにより、データ構造を作成できます。定義した型を拡張して、さらに複雑な型を作成することもできます。

複雑なデータ構造を構築することに加えて、列挙型、特定の範囲の値を持つデータ型、またはプリミティブ型を拡張または制限することによって特定のパターンに従う必要があるデータ型などの特殊な型を記述することもできます。

2.5.1. データ構造の定義

概要

XML スキーマでは、データフィールドのコレクションであるデータユニットは、complexType 要素を使用して定義されます。複合型を指定するには、次の 3 つの情報が必要です。

  1. 定義された型の名前は complexType 要素の name 属性に指定されます。
  2. complexType の最初の子要素は、それがネットワークに配置される際の構造のフィールドの動作を記述します。「複合型の種類」を参照してください。
  3. 定義された構造の各フィールドは、complexType 要素の孫である element 要素で定義されます。「構造の部分を定義」 を参照してください。

たとえば、例2.3「簡易構造」 は、XML スキーマで 2 つの要素を持つ複合型として定義されています。

例2.3 簡易構造

struct personalInfo
{
  string name;
  int age;
};

例2.4「複合型」 は、例2.3「簡易構造」 に記載されている構造の可能な XML スキーママッピングの 1 つを表しています。例2.4「複合型」 で定義された構造によって、name および age の 2 つの要素が含まれるメッセージが生成されます。

.

例2.4 複合型

<complexType name="personalInfo">
  <sequence>
    <element name="name" type="xsd:string" />
    <element name="age" type="xsd:int" />
  </sequence>
</complexType>

複合型の種類

XML スキーマには、複合型のフィールドが XML ドキュメントとして表され、ネットワーク上で渡されるときにどのように編成されるかを記述する 3 つの方法があります。complexType 要素の最初の子要素は、どの複合型が使用されるかを判断します。表2.1「複合型記述子要素」 は、複合型の動作を定義するのに使用される要素を示しています。

表2.1 複合型記述子要素

要素複雑型の動作

sequence

複合型のすべてのフィールドが存在する可能性があり、型定義で指定された順序である必要があります。

all

複合型のすべてのフィールドが存在する可能性がありますが、任意の順序で存在する可能性があります。

choice

構造内の要素の 1 つだけをメッセージに配置できます。

例2.5「簡易で複雑な choice 型」 に示されているように choice 要素を使用して構造が定義されている場合は、name 要素または age 要素のいずれかでメッセージを生成します。

例2.5 簡易で複雑な choice 型

<complexType name="personalInfo">
  <choice>
    <element name="name" type="xsd:string"/>
    <element name="age" type="xsd:int"/>
  </choice>
</complexType>

構造の部分を定義

element 要素を使用して構造を設定するデータフィールドを定義します。すべての complexType 要素には、少なくとも 1 つの element 要素が含まれている必要があります。complexType 要素の各 element 要素は、定義したデータ構造のフィールドを表します。

データ構造のフィールドを完全に説明するために、element 要素には 2 つの必須属性があります。

  • name 属性はデータフィールドの名前を指定し、定義された複合型内で一意である必要があります。
  • type 属性は、フィールドに保存されたデータの型を指定します。タイプは、XML スキーマの単純タイプのいずれか、またはコントラクトで定義されている任意の名前付き複合タイプのいずれかです。

nametype 以外に、element 要素には、minOcurrsmaxOccurs の 2 つの一般的に使用される任意の属性があります。これらの属性は、構造内でフィールドが発生する回数に制限を設けます。デフォルトでは、各フィールドは複合型で 1 回だけ発生します。これらの属性を使用して、フィールドが構造体に表示される必要がある回数、または表示される回数を変更できます。たとえば、例2.6「発生制約のある簡易複合型」 に示されているように、previousJobs というフィールドを定義できます。これは 3 回以上、7 回以下発生する必要があります。

例2.6 発生制約のある簡易複合型

<complexType name="personalInfo">
  <all>
    <element name="name" type="xsd:string"/>
    <element name="age" type="xsd:int"/>
    <element name="previousJobs" type="xsd:string:
             minOccurs="3" maxOccurs="7"/>
  </all>
</complexType>

また、例2.7「minOccurs がゼロに設定された単純な複合型」 で示すように、minOccurs をゼロに設定することにより、minOccurs を使用して age フィールドを任意にすることもできます。この場合、age は省略できますが、データは引き続き有効となります。

例2.7 minOccurs がゼロに設定された単純な複合型

<complexType name="personalInfo">
  <choice>
    <element name="name" type="xsd:string"/>
    <element name="age" type="xsd:int" minOccurs="0"/>
  </choice>
</complexType>

属性の定義

XML ドキュメントでは、属性は要素のタグに含まれています。たとえば、以下のコードの complexType 要素では、name は属性です。複合型の属性を指定するには、complexType 要素定義で attribute 要素を定義します。attribute 要素は、allsequence、または choice 要素の後にのみ表示できます。複合型の属性ごとに attribute 要素を 1 つ指定します。attribute 要素は、complexType 要素の直接の子でなければなりません。

例2.8 属性を持つ複合型

<complexType name="personalInfo">
  <all>
    <element name="name" type="xsd:string"/>
    <element name="previousJobs" type="xsd:string"
             minOccurs="3" maxOccurs="7"/>
  </all>
  <attribute name="age" type="xsd:int" use="required" />
</complexType>

前述のコードでは、attribute 要素は personalInfo 複合型に age 属性があることを指定します。attribute 要素には以下の属性があります。

  • name - 属性を識別する文字列を指定する必須属性。
  • type - フィールドに保存されたデータの型を指定します。タイプは、XML スキーマの単純型の 1 つにすることができます。
  • use - 複合型にこの属性が必要であるかを指定する任意の属性。有効な値は required または optional です。デフォルトでは、この属性はオプションです。

attribute 要素では、任意の default 属性を指定できます。これにより、属性のデフォルト値を指定できます。

2.5.2. 配列の定義

概要

Apache CXF は、コントラクトで配列を定義する 2 つの方法をサポートしています。1 つ目は、値が 1 より大きい maxOccurs 属性のある 1 つの要素を持つ複合型を定義します。2 つ目は、SOAP 配列を使用することです。SOAP 配列は、多次元配列を簡単に定義したり、まばらに配置された配列を送信したりする機能などの追加機能を提供します。

複合型配列

複合型配列は、シーケンス複合型の特殊なケースです。単一要素で複合型を定義し、maxOccurs 属性の値を指定するだけです。たとえば、20 個の浮動小数点数の配列を定義するには、例2.9「複合型配列」 のような複合型を使用します。

例2.9 複合型配列

<complexType name="personalInfo">
  <element name="averages" type="xsd:float" maxOccurs="20"/>
</complexType>

minOccurs 属性の値を指定することもできます。

SOAP 配列

SOAP 配列は、wsdl:arrayType 要素を使用して SOAP-ENC:Array 基本型から派生することによって定義されます。このための構文は 例2.10「wsdl:arrayType を使用して派生した SOAP 配列の構文」 に示されています。definitions 要素が xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" を宣言していることを確認します。

例2.10 wsdl:arrayType を使用して派生した SOAP 配列の構文

<complexType name="TypeName">
  <complexContent>
    <restriction base="SOAP-ENC:Array">
      <attribute ref="SOAP-ENC:arrayType"
                 wsdl:arrayType="ElementType<ArrayBounds>"/>
    </restriction>
  </complexContent>
</complexType>

この構文を使用して、TypeName は新しく定義された配列型の名前を指定します。ElementType は、配列内の要素の型を指定します。ArrayBounds は、配列の次元数を指定します。1 次元配列を指定するには、[] を使用します。2 次元配列を指定するには、[][] または [,] を使用します。

たとえば、例2.11「SOAP 配列の定義」 に記載される SOAP 配列、SOAPStrings は文字列の 1 次元配列を定義します。wsdl:arrayType 属性は、配列要素の型 xsd:string を指定し、次元の数 [] は 1 次元を意味します。

例2.11 SOAP 配列の定義

<complexType name="SOAPStrings">
  <complexContent>
    <restriction base="SOAP-ENC:Array">
      <attribute ref="SOAP-ENC:arrayType"
                 wsdl:arrayType="xsd:string[]"/>
    </restriction>
  </complexContent>
</complexType>

また、SOAP 1.1 仕様で説明されているように、単純な要素を使用して SOAP 配列を記述することもできます。このための構文は 例2.12「要素を使用して派生した SOAP 配列の構文」 に示されています。

例2.12 要素を使用して派生した SOAP 配列の構文

<complexType name="TypeName">
  <complexContent>
    <restriction base="SOAP-ENC:Array">
      <sequence>
        <element name="ElementName" type="ElementType"
                 maxOccurs="unbounded"/>
      </sequence>
    </restriction>
  </complexContent>
</complexType>

この構文を使用する場合、要素の maxOccurs 属性は、常に unbounded に設定する必要があります。

2.5.3. 拡張による型の定義

ほとんどの主要なコーディング言語と同様に、XML スキーマを使用すると、他のデータ型から要素の一部を継承するデータ型を作成できます。これは、拡張による型の定義と呼ばれます。たとえば、planet という新しい要素を追加して、例2.4「複合型」 で定義される personalInfo 構造を拡張する、alienInfo という新しい型を作成できます。

拡張によって定義されるタイプには、次の 4 つの部分があります。

  1. 型の名前は、complexType 要素の name 属性によって定義されます。
  2. complexContent 要素は、新しい型に複数の要素があることを指定します。

    注記

    複合型に新しい属性を追加する場合にのみ、simpleContent 要素を使用できます。

  3. 新しい型が派生される ベース 型と呼ばれる型は、extension 要素の base 属性で指定されます。
  4. 新しい型の要素と属性は、通常の複合型と同様に extension 要素で定義されます。

たとえば、alienInfo は、例2.13「拡張子で定義されたタイプ」 のように定義されます。

例2.13 拡張子で定義されたタイプ

<complexType name="alienInfo">
  <complexContent>
    <extension base="xsd1:personalInfo">
      <sequence>
        <element name="planet" type="xsd:string"/>
      </sequence>
    </extension>
  </complexContent>
</complexType>

2.5.4. 制限によるタイプの定義

概要

XML スキーマを使用すると、XML スキーマの単純型の可能な値を制限することにより、新しい型を作成できます。たとえば、厳密に 9 文字の文字列である単純型 SSN を定義できます。単純型を制限することで定義された新しい型は、simpleType 要素を使用して定義されます。

制限による型の定義には、次の 3 つのことが必要です。

  1. 新しい型の名前は、simpleType 要素の name 属性によって指定されます。
  2. ベース型 と呼ばれる新しい型が派生される単純型は、restriction 要素で指定されます。「基本型の指定」を参照してください。
  3. ベース型の制限を定義する facet というルールは、restriction 要素の子として定義されます。「制限の定義」 を参照してください。

基本型の指定

基本型は、新しいタイプを定義するために制限されているタイプです。これは restriction 要素を使用して指定されます。restriction 要素は simpleType 要素の唯一の子で、ベース型を指定する 1 つの属性 base を持ちます。基本型は、任意の XML スキーマの単純型にすることができます。

たとえば、xsd:int の値を制限して新しい型を定義するには、例2.14「基本型として int の使用」 のような定義を使用します。

例2.14 基本型として int の使用

<simpleType name="restrictedInt">
  <restriction base="xsd:int">
    ...
  </restriction>
</simpleType>

制限の定義

基本型に課せられた制限を定義するルールは、ファセット と呼ばれます。ファセットとは、ファセットの適用方法を定義する 1 つの属性 value を持つ要素です。利用可能なファセットとその有効な value 設定は、ベース型によって異なります。たとえば、xsd:string は、以下を含む 6 つのファセットをサポートします。

  • 長さ
  • minLength
  • maxLength
  • pattern
  • whitespace
  • enumeration

各ファセット要素は restriction 要素の子です。

例2.15「SSN の単純型の説明」 は、ソーシャルセキュリティー番号を表す単純型 SSN の例を示しています。作成される型は xxx-xx-xxxx 形式の文字列です。<SSN>032-43-9876<SSN> は、この型の要素に対する有効な値ですが、<SSN>032439876</SSN> は有効ではありません。

例2.15 SSN の単純型の説明

<simpleType name="SSN">
  <restriction base="xsd:string">
    <pattern value="\d{3}-\d{2}-\d{4}"/>
  </restriction>
</simpleType>

2.5.5. 列挙型の定義

概要

XML スキーマの列挙型は、制限による定義の特殊なケースです。これらは、すべての XML スキーマのプリミティブ型でサポートされる enumeration ファセットを使用して記述されます。最新のプログラミング言語の列挙型と同様に、この型の変数は、指定された値の 1 つのみを持つことができます。

XML スキーマでの列挙型の定義

列挙型を定義するための構文を 例2.16「列挙型の構文」 に示します。

例2.16 列挙型の構文

<simpleType name="EnumName">
  <restriction base="EnumType">
    <enumeration value="Case1Value"/>
    <enumeration value="Case2Value"/>
    ...
    <enumeration value="CaseNValue"/>
  </restriction>
</simpleType>

EnumName は、列挙型の名前を指定します。EnumType は、ケース値のタイプを指定します。CaseNValue (N は 1 以上の任意の数値) は、列挙の特定の各ケースの値を指定します。列挙型は任意の数のケース値を持つことができますが、単純型から派生しているため、一度に有効なケース値は 1 つだけです。

たとえば、列挙 widgetSize で定義された要素を持つ XML ドキュメントは、例2.17「widgetSize 列挙型」 のように、<widgetSize>big</widgetSize> が含まれている場合に有効ですが、<widgetSize>big,mungo</widgetSize> が含まれている場合は有効になりません。

例2.17 widgetSize 列挙型

<simpleType name="widgetSize">
  <restriction base="xsd:string">
    <enumeration value="big"/>
    <enumeration value="large"/>
    <enumeration value="mungo"/>
  </restriction>
</simpleType>