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>
<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>
<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
というメンバーを追加します。otherAttributes
は java.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; } }
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);
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 つの値を取得します。