私はこのようなxmlを持っています:
<todo>
<doLaundry cost="1"/>
<washCar cost="10"/>
<tidyBedroom cost="0" experiencePoints="5000"/>
</todo>
そして、そのXSDスキーマは次のとおりです。
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="todo">
<xs:sequence>
<xs:choice maxOccurs="unbounded">
<xs:element name="doLaundry" type="doLaundry" />
<xs:element name="washCar" type="washCar" />
<xs:element name="tidyBedroom" type="tidyBedroom" />
</xs:choice>
</xs:sequence>
</xs:complexType>
<xs:complexType name="doLaundry">
<xs:attribute name="cost" type="xs:int" />
</xs:complexType>
<xs:complexType name="washCar">
<xs:attribute name="cost" type="xs:int" />
</xs:complexType>
<xs:complexType name="tidyBedroom">
<xs:attribute name="cost" type="xs:int" />
<xs:attribute name="experiencePoints" type="xs:int" />
</xs:complexType>
</xs:schema>
そして、JAXBを介してこのスキーマを処理すると、次のようなメソッドを持つクラスが取得されます。
public class Todo {
public List<Object> getDoLaundryOrWashCarOrTidyBedroom() {
...
}
}
理想的には、他のすべてのXSDタイプが拡張する汎用基本タイプを定義する方法が必要です。 XSDスキーマから生成されたJaxbクラスには、一般的なタスクのリストを返すメソッドが必要です。これにより、新しいタスクをToDoリストに簡単に追加できます。
public class Todo {
public List<Task> getTasks() {
...
}
}
public abstract class Task {
public int getCost() {
...
}
}
public class TidyBedroom extends Task {
public int getExperiencePoints() {
...
}
}
上記のJavaクラスを生成するには、XSDスキーマはどのようになりますか?
ここでBlaiseDoughanの記事の助けを借りて答えを見つけました: http://bdoughan.blogspot.com/2010/11/jaxb-and-inheritance-using-xsitype.html
このスキーマ:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="todo">
<xs:sequence>
<xs:choice maxOccurs="unbounded">
<xs:element name="doLaundry" type="doLaundry" />
<xs:element name="washCar" type="washCar" />
<xs:element name="tidyBedroom" type="tidyBedroom" />
</xs:choice>
</xs:sequence>
</xs:complexType>
<xs:complexType abstract="true" name="Task">
<xs:attribute name="cost" type="xs:int" use="required" />
</xs:complexType>
<xs:complexType name="doLaundry">
<xs:complexContent>
<xs:extension base="Task">
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="washCar">
<xs:complexContent>
<xs:extension base="Task">
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="tidyBedroom">
<xs:complexContent>
<xs:extension base="Task">
<xs:attribute name="experiencePoints" type="xs:int" />
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
バインディングファイルと組み合わせる:
<jxb:bindings version="1.0" xmlns:jxb="http://Java.Sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<jxb:bindings>
<jxb:bindings schemaLocation="todo.xsd" node="/xs:schema/xs:complexType[@name='todo']/xs:sequence/xs:choice">
<jxb:property name="Tasks"/>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
質問で説明したように、抽象クラスと継承クラスを提供します。バインディングファイルは、Jaxbのデフォルトのメソッド名をgetDoLaundryOrWashCarOrTidyBedroom()からgetTasks()に変更します。
xsd:choiceは、@ XmlElementsアノテーションに対応します。この注釈を目的のオブジェクトモデルに直接適用できます。
詳細については、以下を参照してください。
たぶん私は質問を「理解」していませんが、何が問題なのですか。
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="todo">
<xs:sequence>
<xs:choice maxOccurs="unbounded">
<xs:element name="doLaundry" type="task" />
<xs:element name="washCar" type="task" />
<xs:element name="tidyBedroom" type="task" />
</xs:choice>
</xs:sequence>
</xs:complexType>
<xs:complexType name="task">
<xs:attribute name="cost" type="xs:int" />
<xs:attribute name="experiencePoints" type="xs:int" />
</xs:complexType>
</xs:schema>
スキーマで xs:extension を使用すると、スキーマで定義したとおりにJAXBクラスが継承(拡張)されます。