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
文件的相关部分:
更新
总结:
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>