Java JAXB绑定文件将@XmlElement类型设置为字符串,而不是XMLGregorianCalendar

Java JAXB绑定文件将@XmlElement类型设置为字符串,而不是XMLGregorianCalendar,java,xml,generics,jaxb,Java,Xml,Generics,Jaxb,我正在尝试创建一个XmlAdapter,它接收xmlgoriiancalendar并输出xmlgoriiancalendar。其目的是在解组数据时简单地从元素中删除时区数据 看起来是这样的: 公共类TimezoneRemoverAdapter扩展了XmlAdapter{ 公共XMLGregorianCalendar解组(xgc){ if(xgc==null){ 返回null; } xgc.setTimezone(DatatypeConstants.FIELD_未定义); 返回xgc; } 公共X

我正在尝试创建一个
XmlAdapter
,它接收
xmlgoriiancalendar
并输出
xmlgoriiancalendar
。其目的是在解组数据时简单地从元素中删除时区数据

看起来是这样的:

公共类TimezoneRemoverAdapter扩展了XmlAdapter{
公共XMLGregorianCalendar解组(xgc){
if(xgc==null){
返回null;
}
xgc.setTimezone(DatatypeConstants.FIELD_未定义);
返回xgc;
}
公共XMLGregorianCalendar封送员(xgc){
返回xgc;
}
}
这适用于以下代码:

公共类元素{
@xmlement(name=“酒吧日期”)
@XmlJavaTypeAdapter(TimezoneRemoverAdapter.class)
@XmlSchemaType(name=“date”)
受保护的巴达特;
}
不幸的是,当我使用
jaxb bindings.xml
文件生成代码时,上面的代码如下所示:

它将类型设置为
String
,因此我的上述方法不起作用。类型
String
设置正在覆盖它应该是的
XMLGregorianCalendar
类型。我可以手动更改它,但我不希望每次重新生成jaxb文件时都记得更新它。是否有人知道是否有一个选项可以手动设置
@xmlement
类型或将其忽略

以下是
jaxb bindings.xml
文件的相关部分:


更新 总结:

  • 您在某个地方有一个使用日期样式的架构,您无法更改该架构
  • 您有一些使用该模式的XML数据,并指定了带有时区的日期(因此它是
    yyyy-MM-ddXXX
    格式)
  • 您希望从该文件中日期的表示形式中删除
    XXX
    部分(日期本身不附带任何时区,日期只是一个数字)
  • 因此,这可能是一个示例模式:

    <?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>
    
    这是日期适配器

    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);
        }
    }
    
    这是输出,时区被删除了,日期表示也发生了明显的变化

    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>
    

    在您的情况下,必须以不同的方式指定java类型:

    <jxb:javaType 
         name="javax.xml.datatype.XMLGregorianCalendar" 
         xmlType="xs:date"  
         printMethod="foo.bar.TimezoneRemoverAdapter.marshall" 
         parseMethod="foo.bar.TimezoneRemoverAdapter.unmarshall" 
    />
    
    
    
    它对我来说工作得很好,我用更多适配器做了类似的事情:

    <jaxb:globalBindings>    
         <xjc:serializable uid="12343" />
         <jaxb:javaType name="java.util.Date" xmlType="xs:date" printMethod="com.foo.DateAdapter.printDate" parseMethod="com.foo.DateAdapter.parseDate" />
         <jaxb:javaType name="java.util.Date" xmlType="xs:dateTime" printMethod="com.foo.DateAdapter.printDate" parseMethod="com.foo.DateAdapter.parseDate" />
         <jaxb:javaType name="java.util.Date" xmlType="xs:time" printMethod="com.foo.TimeAdapter.printTime" parseMethod="com.foo.TimeAdapter.parseTime" />
    </jaxb:globalBindings>
    
    
    

    我将上述绑定作为
    globalBindings
    放在另一个扩展名为
    .xjb
    的文件中,并在任何需要的地方使用它。

    可能是绑定中的XPath术语找不到所需的元素。您不需要点,因为
    /
    会在整个文档中搜索。更重要的是,尝试用
    '
    包围元素名称。结果项应该如下所示:
    node=“//xs:element[@name='bar-date']”
    XSD看起来像什么?bar date元素是定义为xs:string还是complexType?也许我错了,但我认为marshall/unmarshall追求的是另一个目标,您试图做的在概念上是不正确的。也许时区删除本身是不正确的,为什么会有人这样做?请提供xsd,没有它很难猜测问题,或者重新创建它。bar date元素应该用
    xsd:date
    类型定义。是这样吗?此解决方案不起作用,因为它不使用XML日期格式。1.date的格式是XmlSchemaType所表示的xsd:date。这就是我使用XMLGregorianCalendar的原因。2.我只想删除时区。如果我告诉JAXB对to/from类型使用XMLGregorianCalendar,JAXB将为我进行umarshal/marshal数据编组。3.业务需求。
    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);
    }
    
    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>
    
    <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>
    
    public class DateAdapter extends XmlAdapter<String, Date>
    {
        @Override
        public String marshal(Date date)
        {
            DateFormat df = DateFormat.getDateTimeInstance();
            df.setTimeZone(TimeZone.getTimeZone("GMT"));
    
            return df.format(date);
        }
    
        @Override
        public Date unmarshal(String date) throws ParseException
        {
            DateFormat df = DateFormat.getDateTimeInstance();
            df.setTimeZone(TimeZone.getTimeZone("GMT"));
    
            return df.parse(date);
        }
    
        public static void main(String[] args) throws ParseException
        {
            DateAdapter adapter = new DateAdapter();
    
            String str = adapter.marshal(new Date());
            System.out.println(str); // 16-dic-2013 10.02.09  --> to gmt
    
            Date date = adapter.unmarshal(str);
            System.out.println(date); // Mon Dec 16 11:02:09 CET 2013  --> correct, i'm gmt+1
        }
    }
    
    <jxb:javaType 
         name="javax.xml.datatype.XMLGregorianCalendar" 
         xmlType="xs:date"  
         printMethod="foo.bar.TimezoneRemoverAdapter.marshall" 
         parseMethod="foo.bar.TimezoneRemoverAdapter.unmarshall" 
    />
    
    <jaxb:globalBindings>    
         <xjc:serializable uid="12343" />
         <jaxb:javaType name="java.util.Date" xmlType="xs:date" printMethod="com.foo.DateAdapter.printDate" parseMethod="com.foo.DateAdapter.parseDate" />
         <jaxb:javaType name="java.util.Date" xmlType="xs:dateTime" printMethod="com.foo.DateAdapter.printDate" parseMethod="com.foo.DateAdapter.parseDate" />
         <jaxb:javaType name="java.util.Date" xmlType="xs:time" printMethod="com.foo.TimeAdapter.printTime" parseMethod="com.foo.TimeAdapter.parseTime" />
    </jaxb:globalBindings>