开发者

How do I reuse annotations across complexTypes?

I'm trying to write my first xsd which will have JAXB mapped POJOs generated from it, to be used in a webservice. There will be three related classes which I would like to see expressed in xml as...

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

I'm trying to reuse the declaration of th开发者_Go百科e annotations so the JAXB generated POJOs can belong to the same interface. So far I have the following 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>

This gets me part way there, it gives me xml like...

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

I am having difficulty reusing a type which declares the annotations, while overriding the base of that type. (Note I am trying to get rid of the 'keyValue' element in the above example). Any ideas?

EDIT: I've noticed the xsd snippet does not validate the following xml snippet - that seems to have been lost in the refactoring, but I hope you get the point...


I have found you can use 'attributeGroup' to extract common attributes to create a xsd like...

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

This allows me to reuse the attributes across similar elements, but the generated POJOs do not share a common abstract superclass. I think I'm going to stop auto-generating the POJOs and go with hand built XSD and POJOs, although I'm a little worried that discrepancies between the two.


Why not start from Java classes and do the following. You will need to mark the parent class @XmlTransient to have things work correctly:

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

}

And the subclasses would look like the following:

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

}

Then the following code:

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);
    }

}

Will handle your document:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜