如何获取JAXB对象的命名空间

时间:2012-06-08 14:32:28

标签: java namespaces 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);

5 个答案:

答案 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());
}