JAXB:为共享一个公共XSD的两个XSD生成类



我有两个服务XSD文件AService.XSD和BService.XSD,每个文件都有不同的targetNamespace。这两者都使用一个名为common.XSD的公共XSD。我使用JAXBMaven插件来生成类。

<execution>
    <id>generate-package</id>
    <goals>
        <goal>generate</goal>
    </goals>
    <configuration>
        <extension>true</extension>
        <schemaIncludes>
            <include>schema/Aservice.xsd</include>
            <include>schema/Bservice.xsd</include>                             
        </schemaIncludes>
        <bindingIncludes>                                   
            <include>schema/*.xjb</include>
        </bindingIncludes>
        <generatePackage>com.schema</generatePackage>
        <generateDirectory>src/main/java</generateDirectory>
    </configuration>
</execution>

当我尝试运行此程序时,我会得到以下错误。ValidationType在common.xsd 中定义

org.xml.sax.SAXParseException: A class/interface with the same name "com.schema.ValidationType" is already in use. Use a class customization to resolve this conflict.
..........
org.xml.sax.SAXParseException: (Relevant to above error) another "ValidationType" is generated from here.
......
com.sun.istack.SAXParseException2: Two declarations cause a collision in the ObjectFactory class.

如果我在2个不同的执行中运行2个服务xsd,生成2个不同包,那么我会在两个不同的包中获得相同的ValidationType类。

关于如何让JAXB识别共享模式,有什么想法吗?

您正面临所谓的"变色龙模式",这被认为是一种糟糕的做法。不幸的是,由于JAXB的性质,没有好的解决方案。JAXB注释将bean属性绑定到特定名称空间中的XML元素和属性(在模式编译时确定)。因此,一旦您的模式被编译,就没有官方的好方法来更改您的属性所绑定的元素和属性的名称空间

然而,这正是您想要通过"变色龙"模式实现的。如果在A类中使用,则从"common.xsd"派生的类应该神奇地映射到命名空间A,如果在B类中使用则映射到命名空间B。我可以想象这种魔力,但在现实生活中从未见过。

由于您本质上希望A/common和B/common是"同一个东西",解决它的方法之一是在两次执行中生成A和B(都有common),并使common类实现某个"common"接口。然后,您的软件可以在同一个faschion中处理A/common和B/common,而不管它们实际上是来自不同包的类。

更新:

从评论中,我看到您没有变色龙模式,而只是一个正常的导入。这很容易,只需分别编译common、A和B。请参阅maven-jaxb2-plugin的单独模式编译。

我按照这里的描述定制了包。因此,common.xsd进入com.common.schema,并由AService.xsdBService.xsd共享,这两个包本身都在不同的包中,因为它们在不同的名称空间中。

generatePackage从maven配置中删除,看起来像这样,

<execution>
    <id>generate-package</id>
    <goals>
        <goal>generate</goal>
    </goals>
    <configuration>
        <extension>true</extension>
        <schemaIncludes>
            <include>schema/Aservice.xsd</include>
            <include>schema/Bservice.xsd</include>                            
        </schemaIncludes>
        <bindingIncludes>
            <include>schema/*.xjb</include>
        </bindingIncludes>                                
        <generateDirectory>src/main/java</generateDirectory>
    </configuration>
</execution>