Полиморфизм в XSD-схеме и JAXB-классах - PullRequest
24 голосов
/ 16 февраля 2011

У меня есть 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?

Ответы [ 4 ]

19 голосов
/ 19 февраля 2011

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

6 голосов
/ 17 февраля 2011

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

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

0 голосов
/ 19 февраля 2011

Может быть, я не 'получаю' вопрос, но что не так с ..

<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>
0 голосов
/ 17 февраля 2011

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

...