【问题标题】:How to get the Namespace of a JAXB object如何获取 JAXB 对象的命名空间
【发布时间】:2012-06-12 15:09:39
【问题描述】:

目前我正在使用以下代码将 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);

【问题讨论】:

    标签: java namespaces jaxb


    【解决方案1】:

    你需要使用那个 marshal API 吗?有一个更简单的重载。只要obj的运行时类有@XmlRootElement注解,应该可以简单调用

    marshaller.marshal(obj, out);
    

    【讨论】:

    • 在这种情况下,我没有在对象的类中设置 XmlRootElement 属性。 Marshaller API 是必需的,因此我可以指出这是一个 JAXB_FRAGMENT,即没有 XmlRootElement 的元素。如果我错了,请纠正我。
    • 实际上我正在按照您的建议进行操作。由于中间有新的 JAXBElement(),所以很难阅读...... :-)。
    【解决方案2】:

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

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

    • 如果JAXBIntrospector.isElement 返回真,那么只需使用 JAXBIntrospector.getElementName。
    • 使用反射在ObjectFactory类中查找方法 与返回 JAXBElement 并接受的 JAXB 对象相同的包 作为与 JAXB 相同类的实例的单个参数 目的。调用该方法,然后使用JAXBElement.getName。

    【讨论】:

    • 感谢您的回答! isElement() 在我正在处理的对象上返回 false。
    【解决方案3】:

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

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

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

    【讨论】:

    • 命名空间信息在package-info.java
    • 根据您希望解决方案的通用性,不能保证 xjc 会生成 package-info.class(请参阅 -npa 选项)。
    【解决方案4】:
    JAXBContext jaxbCtx = JAXBContext.newInstance(Instance.class);
    QName qname = jaxbCtx.createJAXBIntrospector().getElementName(instance);
    

    【讨论】:

      【解决方案5】:

      如果要序列化的类上没有 @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());
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-10-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-31
        • 2011-09-19
        • 2014-06-07
        相关资源
        最近更新 更多