Java 如何获取JAXB对象的名称空间

Java 如何获取JAXB对象的名称空间,java,namespaces,jaxb,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

目前,我正在使用以下代码将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);
我想用JAXB“obj”中包含的名称空间替换“硬编码的名称空间”(或者它的一个属性,它们当前应该共享相同的NS)

你知道如何在编组前获取NS信息吗?在输出流中,将显示名称空间。所以他们在“obj”的某个地方

[更新]正如下面的答案所指出的,我不需要设置JAXB_片段属性。我把它改成:

    JAXB.marshal(new JAXBElement<T>(new QName("hard_coded_namespace", rootName), clazz, jaxbObject), out);
JAXB.marshall(新的JAXBElement(新的QName(“硬编码的名称空间”,rootName),clazz,jaxbObject),out);

您需要使用封送处理API吗?还有一个更简单的重载。只要obj的运行时类具有注释@XmlRootElement,您就应该能够简单地调用

marshaller.marshal(obj, out);

Marshaller.JAXB_FRAGMENT
属性的使用实际上与处理非根元素无关。它充当一个标志,以确定是否应限制某些封送处理事件。例如,如果设置了属性,则不会生成开始和结束文档事件

我还没有测试以下内容,但下面是如何创建一些实用程序代码来查找给定JAXB对象的
QName
的基本想法:

  • 如果
    JAXBIntrospector.isElement
    返回true,则只需使用
    JAXBIntrospector.getElementName
  • 使用反射在中的
    ObjectFactory
    类上查找方法 与返回
    JAXBElement
    并获取 与JAXB是同一类的实例的单个参数 对象调用该方法,然后使用
    JAXBElement.getName

目前,我找到的解决方案是:

    String nsURI = "";
    for(Annotation annotation: jaxbObject.getClass().getPackage().getAnnotations()){
        if(annotation.annotationType() == XmlSchema.class){
            nsURI = ((XmlSchema)annotation).namespace();
            break;
        }
    }

欢迎使用更优雅的解决方案:-)

如果类上没有要序列化的@XmlRootElement,则没有其他方法来查找包声明本身(JAXBIntrospector将不起作用):

private QName getQName(最终类clazz){
//没有其他方法,因为它不是@RootXmlElement
最终字符串xmlns;
最终包apapackage=clazz.getPackage();
if(aPackage.isAnnotationPresent(XmlSchema.class)){
xmlns=aPackage.getDeclaredAnnotation(XmlSchema.class).namespace();
}否则{
xmlns=”“;//可能抛出非法
}
返回新的QName(xmlns,clazz.getSimpleName());
}

在这种情况下,我没有在对象的类中设置XmlRootElement属性。Marshaller API是必需的,因此我可以指出这是一个JAXB_片段,即没有XmlRootElement的元素。如果我错了,请纠正我。实际上我正按照你的建议做。因为新的JAXBelEnter()在中间……-很难阅读。命名空间信息位于
package info.java
中,这取决于您希望解决方案的通用性,不能保证package-info.class将由xjc生成(请参见-npa选项)。感谢您的回答!isElement()在我处理的对象上返回false。
JAXBContext jaxbCtx = JAXBContext.newInstance(Instance.class);
QName qname = jaxbCtx.createJAXBIntrospector().getElementName(instance);
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());
}