maven-jaxb2-plugin在同一个项目中重用公共XSD

时间:2018-05-04 13:27:56

标签: java maven jaxb xjc maven-jaxb2-plugin

我有一个项目,它有一个模式A和B,都在同一个命名空间内。两者都导入模式C,它也使用相同的命名空间。如何为A和B生成JAXB类以分离包,同时将生成的C中的JAXB类重用到commons包中?

我已经知道我应该使用剧集并使用为模式C生成的剧集作为模式A和B的单独执行的绑定文件。问题是我不知道如何引用这个生成的剧集文件。 / p>

以下是一个例子:

<plugin>
    <groupId>org.jvnet.jaxb2.maven2</groupId>
    <artifactId>maven-jaxb2-plugin</artifactId>
    <version>0.12.3</version>
    <executions>
        <execution>
            <id>generate-sources-C</id>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <generatePackage>com.mymodel.commons</generatePackage>
                <generateDirectory>${project.build.directory}/generated-sources/xjc-commons</generateDirectory>
                <schemas>
                    <schema><url>src/main/resources/xsd/mymodel/c.xsd</url></schema>
                </schemas>
            </configuration>
        </execution>
        <execution>
            <id>generate-sources-A</id>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <generatePackage>com.mymodel.a</generatePackage>
                <schemas>
                    <schema><url>src/main/resources/xsd/mymodel/a.xsd</url></schema>
                </schemas>
            </configuration>
        </execution>
        <execution>
            <id>generate-sources-B</id>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <generatePackage>com.mymodel.b</generatePackage>
                <schemas>
                    <schema><url>src/main/resources/xsd/mymodel/b.xsd</url></schema>
                </schemas>
            </configuration>
        </execution>
    </executions>
</plugin>

这会导致在以下位置创建剧集文件:

target/generated-sources/xjc-commons/META-INF/sun-jaxb.episode

如何在A和B的执行中引用此剧集/绑定文件? Using Episodes只提到如何从其他jar依赖项中引用一个剧集文件(或者我只是不理解它,这更有可能)。

我看到一个较旧的答案建议pass it as a parameter -b给XJC,但这对我来说似乎没有任何作用。我仍然最终生成了三次与C相同的类。

1 个答案:

答案 0 :(得分:3)

免责声明:我是的作者。

TL; DR这里是test project,演示了如何执行此操作。

这是可能的,但有点毛茸茸,所以请耐心等待。

如果a.xsdb.xsdc.xsd位于同一名称空间中,则a.xsdb.xsd无法导入 {{1他们只能包含它。我们希望将每个XSD生成到自己的包中,比如c.xsdtest.atest.b,并在同一个Maven项目中执行。

为此,我们需要三个单独的test.c执行,每个执行都配置有自己的架构和目标包。例如:

maven-jaxb2-plugin

It is is important to use different target directories for separate executions

好的,这将创建三个目标目录,其中包含三个目标包。下一个问题是 <plugin> <groupId>org.jvnet.jaxb2.maven2</groupId> <artifactId>maven-jaxb2-plugin</artifactId> <executions> <execution> <id>xjc-a</id> <goals> <goal>generate</goal> </goals> <configuration> <generatePackage>test.a</generatePackage> <generateDirectory>${project.build.directory}/xjc-a</generateDirectory> <schemaIncludes> <includes>a.xsd</includes> </schemaIncludes> </configuration> </execution> <!-- xjc-b and xjc-c follow --> </executions> </plugin> 中的类将在c.xsdtest.a生成,我们希望避免这些类。

为实现这一目标,我们必须告诉XJC使用test.b中的类来表示来自test.c的类型。这实际上是剧集文件的用途。此文件通常在c.xsd下生成,它包含已处理模式中所有类型的绑定。以下是为META-INF\sun-jaxb.episode生成的示例:

c.xsd

剧集文件实际上是正常的绑定文件。所以你可以直接在编译中使用它:

<?xml version="1.0" encoding="UTF-8"?>
<bindings xmlns="http://java.sun.com/xml/ns/jaxb" if-exists="true" version="2.1">
  <bindings xmlns:tns="urn:test" if-exists="true" scd="x-schema::tns">
    <schemaBindings map="false">
      <package name="test.c"/>
    </schemaBindings>
    <bindings if-exists="true" scd="~tns:CType">
      <class ref="test.c.CType"/>
    </bindings>
  </bindings>
</bindings>

只剩下一个小问题。 XJC生成的剧集文件也包含此片段:

                <execution>
                    <id>xjc-a</id>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                    <configuration>
                        <generatePackage>test.a</generatePackage>
                        <generateDirectory>${project.build.directory}/xjc-a</generateDirectory>
                        <schemaIncludes>
                            <includes>a.xsd</includes>
                        </schemaIncludes>
                        <bindings>
                            <binding>
                                <fileset>
                                    <directory>${project.build.directory}/xjc-c/META-INF</directory>
                                    <includes>
                                        <include>sun-jaxb.episode</include>
                                    </includes>
                                </fileset>
                            </binding>
                        </bindings>
                    </configuration>
                </execution>

它实际上说“在执行为给定命名空间中的模式生成代码”。如果 <schemaBindings map="false"> <!-- ... --> </schemaBindings> a.xsd位于不同的命名空间中,则不会出现问题。但由于它们位于相同的命名空间中,因此该片段将有效关闭b.xsda.xsd的所有代码生成。

要解决此问题,我们可以对b.xsd生成的sun-jaxb.episode进行后期处理。这可以通过简单的XSLT完成:

c.xsd

此XSLT应在<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" version="1.0"> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()" /> </xsl:copy> </xsl:template> <xsl:template match="jaxb:schemaBindings"/> </xsl:stylesheet> 的代码之后,但在生成c.xsda.xsd的代码之前运行。这可以通过将这些执行分为不同阶段(b.xsdgenerate-sourcesprocess-sources)来实现。

以下是完整的generate-resources

pom.xml