如何获取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对象的命名空间的主要内容,如果未能解决你的问题,请参考以下文章

Xml Jaxb 命名空间和属性顺序

使用命名空间和前缀的 JAXB 解组

如何拥有两个具有不同命名空间和相同 JAXB 类的不同端点?

在 JAXB 编组时删除命名空间前缀

JAXB:如何在没有命名空间的情况下解组 XML

如果命名空间声明在 SOAP 信封上,如何使用 JAXB 解组 SOAP 响应?