目前,我正在使用以下代码
将JAXB对象编组为输出流marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
ByteArrayOutputStream out = new ByteArrayOutputStream();
marshaller.marshal(new JAXBElement(new QName("hard_coded_namespace", clazz.getSimpleName()), clazz, obj), out);
我想将“hard_coded_namespace”替换为JAXB“obj”中包含的命名空间(或其中一个属性,它们目前应该共享相同的NS)。
任何想法如何在编组之前获取NS信息?在输出流中,将显示命名空间。所以他们在“obj”的某个地方。
[更新]正如下面的答案中所指出的,我不需要设置JAXB_FRAGMENT属性。我改成了:
JAXB.marshal(new JAXBElement<T>(new QName("hard_coded_namespace", rootName), clazz, jaxbObject), out);
答案 0 :(得分:4)
目前,这是我找到的解决方案:
String nsURI = "";
for(Annotation annotation: jaxbObject.getClass().getPackage().getAnnotations()){
if(annotation.annotationType() == XmlSchema.class){
nsURI = ((XmlSchema)annotation).namespace();
break;
}
}
欢迎更优雅的解决方案: - )
答案 1 :(得分:1)
您是否需要使用该marshal API?有一个更简单的重载。只要obj的运行时类具有注释@XmlRootElement,您就应该能够简单地调用
marshaller.marshal(obj, out);
答案 2 :(得分:1)
使用Marshaller.JAXB_FRAGMENT
属性与处理非根元素实际上没有任何关系。它充当一个标志,以确定是否应该限制某些封送事件。例如,如果设置了属性,则不会生成开始和结束文档事件。
我没有测试过以下内容,但这里有一个基本概念,即如何创建一些实用程序代码来查找给定JAXB对象的QName
:
JAXBIntrospector.isElement
返回true,则只需使用
JAXBIntrospector.getElementName
。ObjectFactory
类中查找方法
与返回JAXBElement
并获取的JAXB对象相同的包
单个参数,它是与JAXB相同的类的实例
宾语。调用该方法,然后使用JAXBElement.getName
。答案 3 :(得分:0)
JAXBContext jaxbCtx = JAXBContext.newInstance(Instance.class);
QName qname = jaxbCtx.createJAXBIntrospector().getElementName(instance);
答案 4 :(得分:0)
如果要序列化的类上没有 @XmlRootElement ,则没有其他方法可以查找包声明本身(JAXBIntrospector不起作用):
private <T> QName getQName(final Class<T> clazz) {
// No other way since it is not @RootXmlElement
final String xmlns;
final Package aPackage = clazz.getPackage();
if (aPackage.isAnnotationPresent(XmlSchema.class)) {
xmlns = aPackage.getDeclaredAnnotation(XmlSchema.class).namespace();
} else {
xmlns = ""; // May throw illegal
}
return new QName(xmlns, clazz.getSimpleName());
}