JAXB Bindings file Sets @XmlElement type à String au lieu de XMLGregorianCalendar

j'essaie de créer un XmlAdapter qui prend un XMLGregorianCalendar et sorties XMLGregorianCalendar. Le but est de supprimer simultanément les données de fuseau horaire de l'élément lors de la désactivation des données.

Il ressemble à ceci:

public class TimezoneRemoverAdapter extends XmlAdapter<XMLGregorianCalendar, XMLGregorianCalendar> {
    public XMLGregorianCalendar unmarshal(XMLGregorianCalendar xgc) {
        if(xgc == null) {
            return null;
        }
        xgc.setTimezone(DatatypeConstants.FIELD_UNDEFINED);
        return xgc;
    }

    public XMLGregorianCalendar marshal(XMLGregorianCalendar xgc) {
        return xgc;
    }
}

Cela fonctionne très bien pour le code suivant:

public class FooElement {
    @XmlElement(name="bar-date")
    @XmlJavaTypeAdapter(TimezoneRemoverAdapter.class)
    @XmlSchemaType(name = "date")
    protected XMLGregorianCalendar barDate;
}

malheureusement, quand je génère le code en utilisant un jaxb-bindings.xml le fichier, le code ci-dessus ressemble à ceci:

public class FooElement {
    @XmlElement(name="bar-date", type=java.lang.String.class)
    @XmlJavaTypeAdapter(TimezoneRemoverAdapter.class)
    @XmlSchemaType(name = "date")
    protected XMLGregorianCalendar barDate;
}

il met le type à String donc ma méthode ci-dessus ne fonctionne pas. Le type String paramètre est primordial XMLGregorianCalendar tapez ce que ça devrait être. Je peux le changer manuellement, mais je préfère ne pas avoir à le mettre à jour chaque fois que les fichiers jaxb sont régénérés. Est-ce que quelqu'un sait s'il y a une option pour définir manuellement le @XmlElement tapez ou avez-vous ignoré?

Voici la partie pertinente du jaxb-bindings.xml fichier:

<jxb:bindings node=".//xs:element[@name=bar-date]">
    <jxb:property>
        <jxb:baseType>
            <jxb:javaType name="javax.xml.datatype.XMLGregorianCalendar" adapter="foo.bar.TimezoneRemoverAdapter" />
        </jxb:baseType>
    </jxb:property>
</jxb:bindings>
19
demandé sur Daniel Szalay 2013-04-11 01:04:19

2 réponses

UPDATE

résumer:

  1. vous avez un schéma qui utilise le style date quelque part, et vous ne pouvez pas changer le schéma
  2. vous avez des données XML qui utilisent ce schéma et spécifiez une date avec timezone (donc c'est yyyy-MM-ddXXX format)
  3. vous souhaitez supprimer le XXX partie de l' représentation de la date dans ce fichier (la date elle-même n'expédie aucun fuseau horaire, la date n'est qu'un nombre)

donc, cela pourrait être un exemple de schéma:

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <element name="foo">
        <complexType>
            <sequence>
                <element name="bar" type="date" minOccurs="1" maxOccurs="1"/>
            </sequence>
        </complexType>
    </element>
</schema>

cela pourrait être un exemple de données:

<?xml version="1.0" encoding="UTF-8"?>
<foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="foo.xsd">
    <bar>2014-01-01+06:00</bar>
</foo>

c'est JAXB annotated class

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Foo implements Serializable
{
    private static final long serialVersionUID = 1L;

    @XmlElement(name = "bar")
    @XmlJavaTypeAdapter(DateAdapter.class)
    @XmlSchemaType(name = "date")
    private Date bar;

    // getters/setters
}

ceci est un adaptateur de date

public class DateAdapter extends XmlAdapter<String, Date>
{
    @Override
    public String marshal(Date date)
    {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        df.setTimeZone(TimeZone.getTimeZone("GMT"));
        return df.format(date);
    }

    @Override
    public Date unmarshal(String date) throws ParseException
    {
        DateFormat df = new SimpleDateFormat("yyyy-MM-ddXXX");
        return df.parse(date);
    }
}

c'est le principal, de la validation par rapport au schéma:

public static void main(String[] args) throws JAXBException, SAXException
{
    JAXBContext context = JAXBContext.newInstance(Foo.class);

    SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
    Schema schema = sf.newSchema(Foo.class.getResource("/foo.xsd"));

    Unmarshaller unmarshaller = context.createUnmarshaller();
    unmarshaller.setSchema(schema);
    Foo foo = (Foo) unmarshaller.unmarshal(Foo.class.getResource("/foo.xml"));
    System.out.println("unmarshalled: " + foo.getBar());

    Marshaller marshaller = context.createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    marshaller.setProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION, "foo.xsd");
    marshaller.setSchema(schema);
    marshaller.marshal(foo, System.out);
}

et c'est la sortie, le fuseau horaire a été supprimé et la représentation de la date a évidemment changé

unmarshalled: Tue Dec 31 19:00:00 CET 2013
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="foo.xsd">
    <bar>2013-12-31</bar>
</foo>

peut-être cette date représentation le changement n'est pas ce à quoi vous vous attendiez, mais ce n'est pas une préoccupation de JAXB, la date représentée n'a pas changé.

j'oubliais les fixations pour inverser la génération de Foo:

<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc" jaxb:version="2.0">
    <jaxb:globalBindings>
        <xjc:javaType name="java.util.Date" xmlType="xsd:date" adapter="aaa.DateAdapter" />
    </jaxb:globalBindings>
</jaxb:bindings>

FIN DE LA MISE À JOUR


désolé, trop long pour un commentaire...

je ne comprends pas:

  1. pourquoi diable utilisez-vous