2015-01-21 94 views
1

我想指定一个XSD类型的实现类。 这里有一个小例子,模式:Jaxb implClass规范为根元素忽略

<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工具,现在的(但我也有行家-JAXB2-插件测试,相同的结果)。

对于短测试我用下面的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: [email protected]" 

DocumentType doc = (DocumentType)obj; 
Object obj2=doc.getElement(); 
System.out.println("obj2: " + obj2); 
// result: "obj2: [email protected]" 

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

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


拓澄清我的意图:

我不想引用现有的,JAXB注释类,但有附加属性使用自动生成的DocumentType级的基类extionsion和方法。对于后来的直接编组回到XML,我必须保持与XSD-Type的关系。因此,implClass指令实际上是适用于(据我所知)的方法来测试类型类的jaxb代。

它对于内部元素(标签'testElement'内的文档标签'元素')完美工作!不幸的是,unmarshaller没有使用implClass指定的类来正确地实例化根元素。在上面的程序摘录中看到结果 - 评论(doc vs. obj2)。

+0

可能重复(http://stackoverflow.com/questions/26439184/why-is-the-objectfactory-not-used-during-unmarshalling) – lexicore 2015-01-21 10:48:16

+0

不幸它不是。它只是回答了这个问题,为什么ObjectFactory似乎不被使用,但它不回答(至少对我来说不),为什么implClass对另一个元素内的元素工作正常,但对于rootElement不是? – raindrop 2015-01-21 11:47:57

+0

感谢@lexicore的提示上面提到的解决方法是指定一个factoryClass和-method乍一看的确能绕过这个问题。不幸的是,这是不适用的,因为适当的DocumentType-Class将被自动生成,因此如果需要手动修改则不好。不过,implClass对于文档内部相同类型的元素没有使用factoryClass的手动指定是完美的。这就是我不明白的地方?! – raindrop 2015-01-21 12:45:58

回答

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类没有创建,并在ObjectFactorycreateDocument方法是这样的:

@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属性互斥。

的[为什么解组过程中不使用的ObjectFactory?]
+0

谢谢你的回答!不幸的是你误解了我的意图(我看到,我没有说清楚)。正如您指出的那样,使用'ref'指令期望我的类DocumentEx被注释为JAXB,但这不是实例,因为它只是自动生成的DocumentType-Class的特化。根据你的规范摘录,在我看来,也许rootElement实例化的方式不同(使用'new'忽略值类)比内部元素,但如果这是正确的,为什么?! (编辑的问题更好地指出我的意图) – raindrop 2015-01-21 17:06:10