我有一些Java类扩展了一个公共超类。我想用JAXB对它们进行封送/解封,而不会在XML表示中看到超类标记。包含超类的模块不知道当前上下文中可用的子类。
以下是我试图做的事情和我的方法的最小例子:
示例XML:
<root>
<instance>
<member>foo</member>
</instance>
</root>
这应该是一个等效的 Java 表示形式,其中根
具有超类
类型的成员,该成员是实例的父级
:
Root root = new Root();
Instance instance = new Instance();
instance.setMember("foo");
root.setSuperclass(instance);
我主要关心的是从XML表示到Java对象。请注意,我明确不想在XML文件中编写超类标记,因此类似于的内容。
我目前的实现:
@XmlRootElement
class Root {
private Superclass superclass;
@XmlAnyElement
Superclass getSuperclass() { return superclass; }
void setSuperclass(Superclass superclass) { this.superclass = superclass; }
}
@XmlJavaTypeAdapter(ValueAdapter.class)
class Superclass {}
@XmlRootElement(name = "instance")
class Instance extends Superclass {
private String member;
@XmlElement
public String getMember() {return member;}
public void setMember(String member) {this.member = member;}
}
class ValueAdapter extends XmlAdapter<Object, Superclass> {
@Override
public Object marshal(Superclass v) {
return v;
}
@Override
public Superclass unmarshal(Object v) {
Element element = (Element) v;
if (element.getNodeName().equals("instance")) {
Instance instance = new Instance();
instance.setMember(element.getTextContent());
return instance;
}
else throw new IllegalArgumentException();
}
}
在这个例子中,我为
Instance
硬编码了解组
method,但稍后它将访问一个可以注册多个子类的服务。
上面的方法有点用,但看起来完全不对。通过深入Node手动解组子类对象真的很难看。毕竟,我不是在使用JAXB来隐藏这种XML树遍历吗?如果子类有多个成员,比纯字符串更复杂,情况会变得更糟。我对JAXB很陌生,所以我认为我要么滥用了框架,要么忽略了一些显而易见的东西。有什么建议吗?
实际上,有一个更简单的解决方案,不需要任何人工干预,即< code>@XmlElementRef:
@XmlRootElement
class Root {
private Superclass superclass;
@XmlElementRef
Superclass getSuperclass() { return superclass; }
void setSuperclass(Superclass superclass) { this.superclass = superclass; }
}
超类
不需要任何注释,尤其是不需要转换器。
毕竟我已经找到了一个合理的解决方案。这个想法实际上是让JAXB继续发挥它的魔力,但从实例作为新的根元素开始:
public Superclass unmarshal(Object v) throws JAXBException {
Element element = (Element) v;
JAXBContext jc = JAXBContext.newInstance(Instance.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
return unmarshaller.unmarshal(element, Instance.class).getValue();
}
当然,在实际应用程序中创建新上下文的成本很高,不应该每次都重做,但上下文将由了解所有可用实例的提供者外部提供,如下所示:
public Superclass unmarshal(Object v) throws JAXBException {
Element element = (Element) v;
String tag = element.getNodeName();
Class<? extends Superclass> clazz = instanceProvider.getClassForXmlTag(tag);
JAXBContext jc = instanceProvider.getJaxbContextForXmlTag(tag);
Unmarshaller unmarshaller = jc.createUnmarshaller();
return unmarshaller.unmarshal(element, clazz).getValue();
}
问题内容: 考虑这个例子- 我有一个称为Report的类,该类具有Message类型的字段。Message类具有一个称为“ body”的字段,该字段是一个字符串。“ body”可以是任何字符串, 但有时包含格式正确的XML内容 。如何确保当“正文”包含XML内容时,序列化采用XML结构的形式而不是当前的结构? 这是带有输出的代码- 报告 类别 讯息 类别 主要 输出如下- 如您在上面的输出中看到的
我有一个需求,需要从JAXB生成XML。我使用了基本对象,其中只有具有父子关系的键值对,但从未遇到过下面这样的情况。预期的XML 在Java对象中,我不知道如何使用特殊字符
我陷入了一个棘手的问题,我应该使用JAXB库取消marshaX输入流,除了XML结构没有帮助。 我的问题是:标记用于值为>的的
我的真实案例使用了大量具有大量属性的类,版本控制的数量可能是一个很大的数字。我希望存储每个版本的XSD,并通过动态指定包含版本号的XSD名称从Java类生成XMLs。 有没有可能实现我上面描述的需求,或者你有一个类似的解决方案来满足我的需求?
我已经生成java类使用从一个xsd,其中根元素是类型的。 jaxb生成的根元素是 当我尝试解组与该xsd对应的xml并强制转换JaxbElement时,它会引发一个强制转换异常: 片段:
我正在使用JAXB来生成一个肥皂xml请求。我想要的当前xml输出是这个 到目前为止,我已经生成了信封和标题标签,但我有安全标签的问题。 我的问题是,如果我尝试将xmlns设置为package-info.class前缀是正确的,但是和转到根元素(信封)而不是安全标记。这是我得到的输出: 正如您在所需的 xml 输出中看到的 和 命名空间位于安全标记处。如何才能将这些xmlns添加到安全标签?以及用