Как я могу повторно использовать аннотации для complexTypes? - PullRequest
1 голос
/ 02 ноября 2010

Я пытаюсь написать свой первый xsd, в котором будут сгенерированные JAXB POJO, сгенерированные из него, для использования в веб-сервисе. Будет три связанных класса, которые я хотел бы видеть выраженными в xml как ...

<stringKey systemName="string key 1" businessName="Customer">Glorious strings</stringKey>
<numberKey systemName="number key 1" businessName="Invoice number">1025.52</numberKey>
<dateKey systemName="date key 1" businessName="Invoice date">1970-01-01</dateKey>

Я пытаюсь повторно использовать объявление аннотаций, чтобы сгенерированные JAXB POJO могли принадлежать одному интерфейсу. Пока у меня есть следующие xsd ...

<xs:complexType name="dateKey">
    <xs:simpleContent>
        <xs:extension base="namedElement">
            <xs:attribute type="xs:dateTime" name="keyValue" />
        </xs:extension>
    </xs:simpleContent>
</xs:complexType>
<xs:complexType name="namedElement" abstract="true">
    <xs:simpleContent>
        <xs:extension base="xs:string">
            <xs:attribute type="xs:string" name="businessName" />
            <xs:attribute type="xs:string" name="systemName" />
        </xs:extension>
    </xs:simpleContent>
</xs:complexType>

Это дает мне часть пути, это дает мне XML как ...

<dateKey systemName="date key 1" businessName="Invoice date"><keyValue>1970-01-01</keyValue></dateKey>

Мне трудно повторно использовать тип, который объявляет аннотации, переопределяя базу этого типа. (Обратите внимание, я пытаюсь избавиться от элемента 'keyValue' в приведенном выше примере). Есть идеи?

РЕДАКТИРОВАТЬ: я заметил, что xsd-фрагмент не проверяет следующий xml-фрагмент - кажется, что он был потерян в рефакторинге, но я надеюсь, вы поняли ...

Ответы [ 2 ]

1 голос
/ 03 ноября 2010

Я обнаружил, что вы можете использовать attributeGroup для извлечения общих атрибутов, чтобы создать xsd как ...

<xs:complexType name="dateKey">
    <xs:simpleContent>
        <xs:extension base="xs:dateTime">
            <xs:attributeGroup ref="namedElement" />
        </xs:extension>
    </xs:simpleContent>
</xs:complexType>
<xs:attributeGroup name="namedElement">
    <xs:attribute type="xs:string" name="businessName" />
    <xs:attribute type="xs:string" name="systemName" />
</xs:attributeGroup>

Это позволяет мне повторно использовать атрибуты в похожих элементах, но сгенерированные POJO не имеют общего абстрактного суперкласса. Я думаю, что я собираюсь прекратить автоматическую генерацию POJO и идти с XSD и POJO, созданными вручную, хотя меня немного беспокоит это расхождение между ними.

0 голосов
/ 02 ноября 2010

Почему бы не начать с классов Java и сделать следующее.Вам нужно отметить родительский класс @XmlTransient, чтобы все работало правильно:

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlTransient;

@XmlTransient
public class NamedElement {

    private String businessName;
    private String systemName;

    @XmlAttribute
    public String getBusinessName() {
        return businessName;
    }

    public void setBusinessName(String businessName) {
        this.businessName = businessName;
    }

    @XmlAttribute
    public String getSystemName() {
        return systemName;
    }

    public void setSystemName(String systemName) {
        this.systemName = systemName;
    }

}

И подклассы будут выглядеть следующим образом:

import java.util.Date;

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlValue;

@XmlRootElement
public class DateKey extends NamedElement {

    private Date value;

    @XmlValue
    @XmlSchemaType(name="date")
    public Date getValue() {
        return value;
    }

    public void setValue(Date value) {
        this.value = value;
    }

}

Тогда следующий код:

import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(DateKey.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        DateKey dateKey = (DateKey) unmarshaller.unmarshal(new File("input.xml"));

        Marshaller marshaller = jc.createMarshaller();
        marshaller.marshal(dateKey, System.out);
    }

}

Будет обрабатывать ваш документ:

<dateKey systemName="date key 1" businessName="Invoice date">1970-01-01</dateKey>
...