[英]JAXB Bindings File Sets @XmlElement type to String instead of XMLGregorianCalendar
I'm trying to create an XmlAdapter
that takes in an XMLGregorianCalendar
and outputs an XMLGregorianCalendar
. 我正在尝试创建一个
XmlAdapter
,它接受XMLGregorianCalendar
并输出XMLGregorianCalendar
。 The purpose is simlply to remove timezone data from the element when unmarshalling data. 目的是简单地在解组数据时从元素中删除时区数据。
It looks like this: 它看起来像这样:
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;
}
}
This works fine for the following code: 这适用于以下代码:
public class FooElement {
@XmlElement(name="bar-date")
@XmlJavaTypeAdapter(TimezoneRemoverAdapter.class)
@XmlSchemaType(name = "date")
protected XMLGregorianCalendar barDate;
}
Unfortunately, when I generate the code using a jaxb-bindings.xml
file, the above code looks like this: 不幸的是,当我使用
jaxb-bindings.xml
文件生成代码时,上面的代码如下所示:
public class FooElement {
@XmlElement(name="bar-date", type=java.lang.String.class)
@XmlJavaTypeAdapter(TimezoneRemoverAdapter.class)
@XmlSchemaType(name = "date")
protected XMLGregorianCalendar barDate;
}
It sets the type to String
, so my above method doesn't work. 它将类型设置为
String
,因此我的上述方法不起作用。 The type String
setting is overriding the XMLGregorianCalendar
type that it should be. String
类型设置将覆盖它应该是的XMLGregorianCalendar
类型。 I can manually change it, but I'd rather not have to remember to update it every time the jaxb files are regenerated. 我可以手动更改它,但我不必记住每次重新生成jaxb文件时都要更新它。 Does anyone know if there's an option to manually set the
@XmlElement
type or have it ignored? 有没有人知道是否有手动设置
@XmlElement
类型或忽略它的选项?
Here is the relevant portion of the jaxb-bindings.xml
file: 这是
jaxb-bindings.xml
文件的相关部分:
<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>
summarizing: 总结:
yyyy-MM-ddXXX
format) yyyy-MM-ddXXX
格式) XXX
part from the representation of the date in that file (date itself does not ship any timezone, date is just a number) XXX
部分(日期本身不发送任何时区,日期只是一个数字) so this could be a sample schema: 所以这可能是一个示例模式:
<?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>
this could be a sample data: 这可能是一个示例数据:
<?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>
this is JAXB annotated class 这是JAXB注释类
@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
}
this is date adapter 这是日期适配器
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);
}
}
this is the main, validating against the schema: 这是主要的,验证模式:
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);
}
and this is the output, timezone has been removed and date representation has obviously changed 这是输出,时区已被删除,日期表示已明显改变
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>
maybe this date representation change is not what you'd expect, but this is not a JAXB concern, the date represented has not changed. 也许这个日期表示更改不是您所期望的,但这不是JAXB关注的问题,所代表的日期没有改变。
i was forgetting the bindings to reverse generate Foo: 我忘了绑定反向生成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>
sorry, too long for a comment... 对不起,评论太久了......
i can't understand: 我无法理解:
XmlGregorianCalendar
? XmlGregorianCalendar
? marshal
/ unmarshal
( serialize
/ deserialize
) to the very same data structure? marshal
/ unmarshal
( serialize
/ deserialize
serialize
)到完全相同的数据结构? and 和
java.util.Date
java.util.Date
marshal
/ unmarshal
should always involve String
s (at least for XML) marshal
/ unmarshal
应该总是涉及String
(至少对于XML) however 然而
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
}
}
You have to specify the java type differently, in your case: 在您的情况下,您必须以不同的方式指定java类型:
<jxb:javaType
name="javax.xml.datatype.XMLGregorianCalendar"
xmlType="xs:date"
printMethod="foo.bar.TimezoneRemoverAdapter.marshall"
parseMethod="foo.bar.TimezoneRemoverAdapter.unmarshall"
/>
It works fine for me and I did something similar with more adapters: 它适用于我,我做了类似的更多适配器:
<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>
I put the above bindings as a globalBindings
in a different file with .xjb
extension and I use it everywhere I need it. 我把上面的绑定作为
globalBindings
在不同的文件.xjb
扩展,我用它无处不在,我需要它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.