Menu Close

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

概要

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

36.1. 任意の要素の使用

概要

XML スキーマの any 要素を使用して、複合型の定義にワイルドカードのプレースホルダーを作成します。XML 要素が XML スキーマの any 要素に対してインスタンス化されると、有効な任意の XML 要素として使用できます。any 要素は、インスタンス化した XML 要素のコンテンツまたは名前のいずれにも制限を設けません。

たとえば、例36.1「any 要素で定義された XML スキーマ型」で定義された複合型では、例36.2「any 要素を使用する XML ドキュメント」に示されている XML 要素のいずれかをインスタンス化できます。

例36.1 any 要素で定義された XML スキーマ型

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

例36.2 any 要素を使用する XML ドキュメント

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

XML スキーマの any 要素は、Java Object オブジェクトまたは Java org.w3c.dom.Element オブジェクトのいずれかにマッピングされます。

XML スキーマでの指定

any 要素は、sequence 複合型や choice 複合型を定義するときに使用できます。多くの場合、any 要素は空の要素です。ただし、annotation 要素を子として取ることができます。

表36.1「XML スキーマの any 要素の属性」any 要素の属性を説明します。

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

属性説明

namespace

XML ドキュメントで要素をインスタンス化するために使用できる要素の namespace を指定します。有効な値を以下に示します。

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

maxOccurs

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

minOccurs

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

processContents

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

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

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

例36.3 any 要素で定義された複合型

<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「any 要素を使用する Java クラス」に、例36.3「any 要素で定義された複合型」で定義された複合型がどのように Java クラスにマッピングされるかを示します。

例36.4 any 要素を使用する 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 アノテーションを使用して、ランタイムのマッピングに型を追加できます。