对于rootElement,忽略了Jaxb implClass规范

时间:2015-01-21 10:19:21

标签: java jaxb jaxb2

我正在尝试为XSD-Type指定一个实现类。 这是一个最小的示例模式:

<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="rd.test" 
        xmlns:tns="rd.test" elementFormDefault="qualified"
        xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0">
  <complexType name="DocumentType">
    <annotation>
      <appinfo>
        <jaxb:class implClass="rd.DocumentEx" />
      </appinfo>
    </annotation>
    <sequence>
      <element name="element" type="tns:DocumentType" />
    </sequence>
    <attribute name="title" type="string" />
  </complexType>
<element name="document" type="tns:DocumentType"/>
</schema>

我现在正在使用Java JDK(1.7)中的标准xjc工具(但我也测试了maven-jaxb2-plugin,结果相同)。

对于简短测试,我使用了以下XML文档:

<?xml version='1.0' standalone='yes' ?>
<document title="testDocument">
  <element title="testElement" />
</document>

当我运行以下测试程序时,顶级文档元素(testDocument)和包含的子元素(testElement)的结果不同。根类型为“DocumentType”,即忽略指定的implClass-directive,而该元素的类型为“DocumentEx”,这是预期的结果。 在生成的ObjectFactory中,相应的实例化似乎是正确的,但似乎没有用于rootElement:

  public DocumentType createDocumentType() {
    return new DocumentEx();
  }

以下是测试程序:

InputStream inp=new FileInputStream(new File("test.xml"));
JAXBContext jaxbContext = JAXBContext.newInstance("test.rd");
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();

JAXBElement el = (JAXBElement)unmarshaller.unmarshal(inp);
Object obj = el.getValue();
System.out.println("doc: " + obj);
// result: "doc: test.rd.DocumentType@d1c5bb0"

DocumentType doc = (DocumentType)obj;
Object obj2=doc.getElement();
System.out.println("obj2: " + obj2);
// result: "obj2: rd.DocumentEx@d1c5bb0"

如果我为元素而不是complexType指定implClass,我会得到相同的结果。

为什么root元素会忽略implClass? 任何想法和提示都表示赞赏!


扩展以澄清我的意图:

我不想引用现有的带有jaxb注释的类,但是使用自动生成的DocumentType-Class作为extionsion的基类以及其他属性和方法。为了以后直接编组回XML,我必须保持与XSD-Type的关系。因此,implClass指令实际上是适当的(据我所知)方法来检测类型类的jaxb生成。

它完美适用于内部元素(文档标记内标题为'testElement'的'元素')!!不幸的是,unmarshaller不会使用implClass指定的类来正确地实例化根元素。请参阅上面的程序摘录中的结果 - 注释(doc vs. obj2)。

1 个答案:

答案 0 :(得分:0)

对于您要查找的行为,我认为您要指定ref而不是impl

<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="rd.test"
        xmlns:tns="rd.test" elementFormDefault="qualified"
        xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0">
    <complexType name="DocumentType">
        <annotation>
            <appinfo>
                <jaxb:class ref="rd.DocumentEx" />
            </appinfo>
        </annotation>
        <sequence>
            <element name="element" type="tns:DocumentType" />
        </sequence>
        <attribute name="title" type="string" />
    </complexType>
    <element name="document" type="tns:DocumentType"/>
</schema>

这告诉JAXB将rd.DocumentEx类用于DocumentType复杂类型。现在没有创建DocumentType类,createDocument上的ObjectFactory方法如下所示:

@XmlElementDecl(namespace = "rd.test", name = "document")
public JAXBElement<DocumentEx> createDocument(DocumentEx value) {
    return new JAXBElement<DocumentEx>(_Document_QNAME, DocumentEx.class, null, value);
}

来自JAXB 2.2规范的第7.7.1节:

  

•如果指定implClass,则为实现类的名称   className并且必须包含完整的包名称。请注意这一点   自定义仅影响className工厂的返回值   方法。使用new创建时,将忽略此自定义   模式派生的Value类的实例。

     

•ref如果指定,则为   在架构编译器外部提供的值类的名称。   此自定义导致架构编译器引用此外部   类,而不是生成定义。它必须包括   完整的包名。该属性与。互斥   className属性和implClass属性。