36.3. バインドされていない属性の使用

概要

XML スキーマには、複合型定義内の任意の属性のプレースホルダーを残すことができるメカニズムがあります。このメカニズムを使用すると、任意の属性を持つことができる複合型を定義できます。たとえば、3 つの属性を指定せずに、要素 <robot name="epsilon" />、<robot age="10000" />、または <robot type="weevil" /> を定義するタイプを作成できます。これは、データに柔軟性が必要な場合に特に役立ちます。

XML スキーマでの定義

宣言されていない属性は、anyAttribute 要素を使用して XML スキーマで定義されます。属性要素を使用できる場所であればどこでも使用できます。例36.7「宣言されていない属性を持つ複合型」に示されているように、anyAttribute 要素には属性がありません。

例36.7 宣言されていない属性を持つ複合型

<complexType name="arbitter">
  <sequence>
    <element name="name" type="xsd:string" />
    <element name="rate" type="xsd:float" />
  </sequence>
  <anyAttribute />
</complexType>

定義された型 arbitter には 2 つの要素があり、任意の型の属性を 1 つ設定できます。例36.8「ワイルドカード属性で定義された要素の例」 に記載されている 3 つの要素は、すべて複合型 arbitter から生成できます。

例36.8 ワイルドカード属性で定義された要素の例

<officer rank="12"><name>...</name><rate>...</rate></officer>
<lawyer type="divorce"><name>...</name><rate>...</rate></lawyer>
<judge><name>...</name><rate>...</rate></judge>

Java へのマッピング

anyAttribute 要素を含む複合型が Java にマップされると、コードジェネレーターは、生成されたクラスに otherAttributes というメンバーを追加します。otherAttributesjava.util.Map<QName, String> タイプであり、マップのライブインスタンスを返すゲッターメソッドを持ちます。ゲッターから返されたマップはライブであるため、マップへの変更は自動的に適用されます。例36.9「宣言されていない属性を持つ複合型のクラス」 は、例36.7「宣言されていない属性を持つ複合型」 で定義された複合型に対して生成されたクラスを示します。

例36.9 宣言されていない属性を持つ複合型のクラス

public class Arbitter {

    @XmlElement(required = true)
    protected String name;
    protected float rate;

    @XmlAnyAttribute private Map<QName, String> otherAttributes = new HashMap<QName, String>();

    public String getName() {
        return name;
    }

    public void setName(String value) {
        this.name = value;
    }

    public float getRate() {
        return rate;
    }

    public void setRate(float value) {
        this.rate = value;
    }

    public Map<QName, String> getOtherAttributes() { return otherAttributes; }

}

宣言されていない属性の操作

生成されたクラスの otherAttributes メンバーには、Map オブジェクトが設定される必要があります。マップは QNames を使用してキーが付けられます。マップを取得すると、オブジェクトに設定されている任意の属性にアクセスして、オブジェクトに新しい属性を設定できます。

例36.10「宣言されていない属性の操作」 は、宣言されていない属性を操作するためのサンプルコードを示しています。

例36.10 宣言されていない属性の操作

Arbitter judge = new Arbitter();
Map<QName, String> otherAtts = judge.getOtherAttributes();

QName at1 = new QName("test.apache.org", "house");
QName at2 = new QName("test.apache.org", "veteran");

otherAtts.put(at1, "Cape");
otherAtts.put(at2, "false");

String vetStatus = otherAtts.get(at2);

例36.10「宣言されていない属性の操作」 のコードは、以下を行います。

宣言されていない属性を含むマップを取得します。

属性を操作する QName を作成します。

属性の値をマップに設定します。

属性の 1 つの値を取得します。