如何获取JAXB对象的命名空间
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何获取JAXB对象的命名空间相关的知识,希望对你有一定的参考价值。
目前,我正在使用以下代码将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);
答案
现在,这是我找到的解决方案:
String nsURI = "";
for(Annotation annotation: jaxbObject.getClass().getPackage().getAnnotations()){
if(annotation.annotationType() == XmlSchema.class){
nsURI = ((XmlSchema)annotation).namespace();
break;
}
}
欢迎更优雅的解决方案:-)
另一答案
你需要使用那个marshal API吗?有一个更简单的重载。只要obj的运行时类具有注释@XmlRootElement,您就应该能够简单地调用
marshaller.marshal(obj, out);
另一答案
使用Marshaller.JAXB_FRAGMENT
属性与处理非根元素实际上没有任何关系。它充当一个标志,以确定是否应该限制某些封送事件。例如,如果设置了属性,则不会生成开始和结束文档事件。
我没有测试过以下内容,但是这里有一个基本概念,我将如何创建一些实用程序代码来查找给定JAXB对象的QName
:
- 如果
JAXBIntrospector.isElement
返回true,那么只需使用JAXBIntrospector.getElementName
。 - 使用反射在与返回
ObjectFactory
的JAXB对象相同的包中的JAXBElement
类上查找方法,并获取与JAXB对象相同的类的实例。调用该方法,然后使用JAXBElement.getName
。
另一答案
JAXBContext jaxbCtx = JAXBContext.newInstance(Instance.class);
QName qname = jaxbCtx.createJAXBIntrospector().getElementName(instance);
另一答案
如果要序列化的类上没有@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());
}
以上是关于如何获取JAXB对象的命名空间的主要内容,如果未能解决你的问题,请参考以下文章