第36章 ワイルドカードタイプの使用

概要

スキーマ作成者がバインディング要素または属性を定義された型に延期したい場合があります。このような場合、XML スキーマはワイルドカードプレースホルダーを指定するための 3 つのメカニズムを提供します。これらはすべて、XML スキーマ機能を保持する方法で Java にマップされます。

36.1. 任意の要素の使用

概要

XML Schema any 要素は、複雑なタイプ定義にワイルドカードの配置ホルダーを作成するために使用されます。XML スキーマ any 要素に対して XML 要素がインスタンス化されると、有効な XML 要素を使用できます。any 要素は、インスタンス化された XML 要素の名前に制約をかけません。

たとえば、例36.1「任意の要素で定義された XML スキーマタイプ」 で定義された複合型が与えられた場合 例36.2「任意の要素を含む XML ドキュメント」 に示す XML 要素のいずれかをインスタンス化できます。

例36.1 任意の要素で定義された XML スキーマタイプ

<element name="FlyBoy">
  <complexType>
    <sequence>
      <any />
      <element name="rank" type="xsd:int" />
    </sequence>
  </complexType>
</element>

例36.2 任意の要素を含む XML ドキュメント

<FlyBoy>
  <learJet>CL-215</learJet>
  <rank>2</rank>
</element>
<FlyBoy>
  <viper>Mark II</viper>
  <rank>1</rank>
</element>

XML Schema any 要素は、Java オブジェクト オブジェクトまたは Java org.w3c.dom.Element オブジェクトにマッピングされます。

XML スキーマでの指定

シーケンスの複雑な型や複雑なタイプを定義するときに、any 要素を使用できます。多くの場合、any 要素は空の要素です。ただし、annotation 要素を子として取ることができます。

表36.1「XML スキーマの属性任意の要素」 は、any 要素の属性を記述します。

表36.1 XML スキーマの属性任意の要素

属性説明

namespace

XML ドキュメントで要素をインスタンス化するために使用できる要素の名前空間を指定します。有効な値は、以下の通りです。

##any
任意の名前空間の要素を使用できることを指定します。これがデフォルトです。
##other
親要素の名前空間以外 の任意の名前空間の要素を使用できることを指定します。
##local
名前空間のない要素を使用する必要があることを指定します。
##targetNamespace
親要素の名前空間の要素を使用する必要があることを指定します。
URI のスペース区切りリスト #\#local および \#\#targetNamespace
リストされた名前空間のいずれかの要素を使用できることを指定します。

maxOccurs

要素のインスタンスが親要素に表示される最大回数を指定します。デフォルト値は 1 です。要素のインスタンスを無制限に表示可能であることを指定するには、属性の値を unbounded に設定します。

minOccurs

要素のインスタンスが親要素に表示される最小回数を指定します。デフォルト値は 1 です。

processContents

任意の要素をインスタンス化するために使用される要素を検証する方法を指定します。有効な値は以下のとおりです。

strict
要素を適切なスキーマに対して検証する必要があることを指定します。これはデフォルト値です。
lax
要素を適切なスキーマに対して検証する必要があることを指定します。検証できない場合、エラーは出力されません。
skip
要素を検証しないことを指定します。

例36.3「任意の要素で定義された複合型」に、any 要素で定義された複合型を示します。

例36.3 任意の要素で定義された複合型

<complexType name="surprisePackage">
  <sequence>
    <any processContents="lax" />
    <element name="to" type="xsd:string" />
    <element name="from" type="xsd:string" />
  </sequence>
</complexType>

Java へのマッピング

XML スキーマの any 要素により、any という名前の Java プロパティーが作成されます。プロパティーには、ゲッターメソッドとセッターメソッドが関連付けられています。作成されるプロパティーのタイプは、要素の processContents 属性の値によって異なります。any 要素の processContents 属性が skip に設定されている場合、要素は org.w3c.dom.Element オブジェクトにマッピングされます。processContents 属性の値がそれ以外の場合、any 要素は Java Object オブジェクトにマッピングされます。

生成されたプロパティーは @XmlAnyElement アノテーションで禁止されています。このアノテーションには、データをマーシャリングする際のランタイムに指示するオプションの lax プロパティーがあります。デフォルト値は false で、データを org.w3c.dom.Element オブジェクトに自動的にマーシャリングするようにランタイムに指示します。laxtrue に設定: ランタイムが、データを JAXB タイプにマーシャリングしようとします。any 要素の processContents 属性が skip に設定されている場合は、lax プロパティーはデフォルト値に設定されます。processContents 属性の他のすべての値の場合、laxtrue に設定されます。

例36.4「任意の要素を持つ Java クラス」 で定義された複合型がどのように定義されているかを示し、例36.3「任意の要素で定義された複合型」 Java クラスにマップされます。

例36.4 任意の要素を持つ Java クラス

public class SurprisePackage {

    @XmlAnyElement(lax = true) protected Object any;
    @XmlElement(required = true)
    protected String to;
    @XmlElement(required = true)
    protected String from;

    public Object getAny() { return any; }

    public void setAny(Object value) { this.any = value; }

    public String getTo() {
        return to;
    }

    public void setTo(String value) {
        this.to = value;
    }

    public String getFrom() {
        return from;
    }

    public void setFrom(String value) {
        this.from = value;
    }

}

マーシャリング

any 要素の Java プロパティーにその laxfalse に設定されているか、プロパティーが指定されていない場合、ランタイムは XML データの JAXB オブジェクトへの解析を試行しません。データは常に DOM Element オブジェクトに保存されます。

any 要素の Java プロパティーの laxtrue に設定されている場合、ランタイムは XML データを適切な JAXB オブジェクトにマーシャリングしようとします。ランタイムは、次の手順を使用して適切な JAXB クラスを識別しようとします。

  1. XML 要素の要素タグをランタイムに認識されている要素のリストと照合します。一致するものが見つかった場合、ランタイムは XML データを要素の適切な JAXB クラスにマーシャリングします。
  2. XML 要素の xsi:type 属性をチェックします。一致するものが見つかった場合、ランタイムは XML 要素をそのタイプの適切な JAXB クラスにマーシャリングします。
  3. 一致するものが見つからない場合は、XML データを DOM Element オブジェクトにマーシャリングします。

通常、アプリケーションのランタイムは、そのコントラクトに含まれるスキーマから生成されたすべてのタイプを認識しています。これには、コントラクトの wsdl:types 要素で定義された型や、インクルージョンによってコントラクトに追加されたデータ型、他のスキーマのインポートによってコントラクトに追加されたデータ型が含まれます。「ランタイムマーシャラーへのクラスの追加」 で説明される @XmlSeeAlso アノテーションを使用して、追加の型をランタイムを認識させることもできます。

アンマーシャリング

any 要素の Java プロパティーの laxfalse に設定されているか、プロパティーが指定されていない場合、ランタイムは DOM Element オブジェクトだけを受け入れます。他のタイプのオブジェクトを使用しようとすると、マーシャリングエラーが発生します。

any 要素の Java プロパティーの laxtrue に設定されている場合、ランタイムは Java データ型とそれらが表す XML スキーマ構造との間の内部マッピングを使用して、ワイヤに書き込む XML 構造を判断します。ランタイムがクラスを認識し、それを XML スキーマ構造にマッピングできる場合は、データを書き出して xsi:type 属性を挿入し、要素に含まれるデータの型を特定します。

ランタイムが Java オブジェクトを既知の XML スキーマ構造にマップできない場合、マーシャリング例外が出力されます。「ランタイムマーシャラーへのクラスの追加」 で説明されている @XmlSeeAlso アノテーションを使用して、ランタイムのマッピングに型を追加できます。