JAXB - 如何根据 XML 元素的值设置 xsi:type?
我必须生成一个 xml 元素,该元素可以具有任何“原始类型”(xsd:string、xsd:boolean 等)的值。示例:
<field xsi:type="xsd:string" name="aString">String Value</field>
<field xsi:type="xsd:date" name="aDate">2011-10-21</field>
...
所以,我尝试了两种实现:
public class Field {
@XmlAttribute
private String name;
@XmlValue
Object value;
}
并且...
public class Field<T> {
@XmlAttribute
private String name;
@XmlValue
T value;
}
我正在测试它:
Marshaller marshaller = JAXBContext.newInstance(Field.class).createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.setProperty("com.sun.xml.bind.xmlDeclaration", Boolean.FALSE);
Field field = new Field();
field.name = "name";
field.value = "value";
ByteArrayOutputStream stream = new ByteArrayOutputStream();
marshaller.marshal(field, new PrintWriter(stream));
System.out.println(stream);
但是当我尝试实例化 JAXBContext 时,我收到了这个 NullPointerException
。
java.lang.NullPointerException
at com.sun.xml.bind.v2.runtime.reflect.TransducedAccessor.get(TransducedAccessor.java:165)
at com.sun.xml.bind.v2.runtime.property.ValueProperty.<init>(ValueProperty.java:77)
at com.sun.xml.bind.v2.runtime.property.PropertyFactory.create(PropertyFactory.java:106)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.<init>(ClassBeanInfoImpl.java:179)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:515)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:330)
at
这个想法是允许对字段元素进行模式验证(它在模式中定义,必须在每个实例中设置其类型)。那么,即使这是一个 Bug(或不是)...JAXB 如何将正确的 xsi:type
放入此字段实例?我在这里缺少一个概念?
我知道问题可能在于 @XmlValue
的使用,因为存在以下限制(来自 javadoc):
- 最多可以使用 @XmlValue 注释对一个字段或属性进行注释。
- @XmlValue 可以与以下注释一起使用:XmlList。然而,这是多余的,因为 XmlList 将类型映射到简单的架构类型,该架构类型是通过列表派生的,就像 XmlValue 一样。
- 如果字段或属性的类型是集合类型,则集合项类型必须映射到简单架构类型。
- 如果字段或属性的类型不是集合类型,则该类型必须映射到 XML 架构简单类型。
...因为 Object
或通用 T
不一定是 XML Schema 简单类型,因此这种方法似乎不是正确的方法...
提前致谢 .. 。
I have to generate a xml element that can have as value any "primitive type" (xsd:string, xsd:boolean, etc). Examples:
<field xsi:type="xsd:string" name="aString">String Value</field>
<field xsi:type="xsd:date" name="aDate">2011-10-21</field>
...
So, I tried two implementations:
public class Field {
@XmlAttribute
private String name;
@XmlValue
Object value;
}
and ...
public class Field<T> {
@XmlAttribute
private String name;
@XmlValue
T value;
}
I'm testing this with:
Marshaller marshaller = JAXBContext.newInstance(Field.class).createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.setProperty("com.sun.xml.bind.xmlDeclaration", Boolean.FALSE);
Field field = new Field();
field.name = "name";
field.value = "value";
ByteArrayOutputStream stream = new ByteArrayOutputStream();
marshaller.marshal(field, new PrintWriter(stream));
System.out.println(stream);
But I'm getting this NullPointerException
when I try to instantiate the JAXBContext.
java.lang.NullPointerException
at com.sun.xml.bind.v2.runtime.reflect.TransducedAccessor.get(TransducedAccessor.java:165)
at com.sun.xml.bind.v2.runtime.property.ValueProperty.<init>(ValueProperty.java:77)
at com.sun.xml.bind.v2.runtime.property.PropertyFactory.create(PropertyFactory.java:106)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.<init>(ClassBeanInfoImpl.java:179)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:515)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:330)
at
The idea is allow schema validation for the field element (It is define in a schema must its type will be set in each instance). So, even is this a Bug (or not) ... how JAXB will put the correct xsi:type
to this field instance? I'm missing a concept here?
I know that maybe the problem is the usage of the @XmlValue
because of this restrictions (from the javadoc):
- At most one field or property can be annotated with the @XmlValue annotation.
- @XmlValue can be used with the following annotations: XmlList. However this is redundant since XmlList maps a type to a simple schema type that derives by list just as XmlValue would.
- If the type of the field or property is a collection type, then the collection item type must map to a simple schema type.
- If the type of the field or property is not a collection type, then the type must map to a XML Schema simple type.
... because an Object
or a generic T
is not necessarily a XML Schema simple type, this approach seems not to be the correct one ...
Thanks in advance ...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我已经确认了您在参考和 EclipseLink JAXB (MOXy) JAXB 的实现。您看到的问题是由于使用
@XmlValue
造成的。如果value
属性映射为@XmlElement
,您将看到xsi:type
属性按预期显示。我已在 EclipseLink JAXB (MOXy) 中输入以下错误来跟踪此问题:
根据您的域模型的外观,您可能对 EclipseLink JAXB (MOXy) 的
@XmlPath
扩展感兴趣:更新
此问题现已在 EclipseLink 2.3.3 和 EclipseLink 中修复2.4.0。该修复程序从 2012 年 3 月 17 日开始在这些流中提供,可以从以下位置获取:
I have confirmed the issue you are seeing in both the reference and EclipseLink JAXB (MOXy) implementations of JAXB. The problem you are seeing is due to use of
@XmlValue
. If thevalue
property was mapped as an@XmlElement
you would see thexsi:type
attribute appear as expected.I have entered the following bug to track this issue in EclipseLink JAXB (MOXy):
Depending upon what your domain model looks like you may be interested in the
@XmlPath
extension from EclipseLink JAXB (MOXy):UPDATE
This issue has now been fixed in the EclipseLink 2.3.3 and EclipseLink 2.4.0. The fix is available in these streams starting March 17, 2012 and can be obtained from: