Подтвердить что ты не робот

Полиморфизм в схеме XSD и классах JAXB

У меня есть 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. Классы Jaxb, созданные из схемы XSD, должны иметь метод для возврата списка общих задач. Это упростит добавление новых задач в список задач:

public class Todo {

    public List<Task> getTasks() {
        ...
    }

}

public abstract class Task {
    public int getCost() {
        ...
    }
}

public class TidyBedroom extends Task {
    public int getExperiencePoints() {
        ...
    }
}

Какова должна быть схема XSD для генерации вышеуказанных классов Java?

4b9b3361

Ответ 1

Я нашел ответ с помощью статьи Блейза Доуана: 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().

Ответ 2

xsd: выбор соответствует аннотации @XmlElements. Вы можете применить эту аннотацию непосредственно к вашей желаемой объектной модели.

Для получения дополнительной информации см.

Ответ 3

Используйте xs: extension в своей схеме, и ваши классы JAXB будут наследоваться (расширены), как вы определяете в своей схеме.

Ответ 4

Возможно, я не "получаю" вопрос, но что не так с.

<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>