maven-jaxb2-plugin 在同一项目中重用公共 XSD [英] maven-jaxb2-plugin reusing commons XSD within same project

查看:33
本文介绍了maven-jaxb2-plugin 在同一项目中重用公共 XSD的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a project which has a schema A and B, both within the same namespace. Both import schema C which also uses the same namespace. How can I generate JAXB classes for A and B to separate packages, while reusing the JAXB classes from C generated to a commons package?

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

I already know I should probably be using episodes and use the episode generated for schema C as bindings file for the separate executions of schema's A and B. Problem is I don't know how to refer to this generated episode file.

这是一个例子:

<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>

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

This causes an episode file to be created under:

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

如何在 A 和 B 的执行中引用此情节/绑定文件?Using Episodes 只提到如何从其他地方引用剧集文件jar 依赖项(或者我根本没有正确理解它,这更有可能).

How do I refer to this episode/bindings file in executions for A and B? Using Episodes only mentions how to refer to an episode file from other jar dependencies (or I simply didn't understand it properly, which is more likely).

我看到一个较旧的答案建议 将其作为参数传递 -b到XJC,但这似乎对我没有任何帮助.我仍然会从 C 中生成相同的类 3 次.

I've seen an older answer suggest to pass it as a parameter -b to XJC, but that didn't seem to do anything for me. I still end up with the same class from C generated three times.

推荐答案

免责声明:我是.

TL;DR 这是一个测试项目 它演示了如何做到这一点.

TL;DR here's a test project which demonstrates how to do this.

这是可能的,但有点毛,所以请多多包涵.

This is possible, but is a bit hairy, so please bear with me.

如果a.xsdb.xsdc.xsd在同一个命名空间,a.xsdb.xsd 不能import c.xsd,只能include.我们希望将每个 XSD 生成到其自己的包中,例如 test.atest.btest.c 并在其中完成同一个 Maven 项目.

If a.xsd, b.xsd and c.xsd are in the same namespace, a.xsd and b.xsd cannot import c.xsd, they can only include it. We want to generate each of the XSDs into its own package, say test.a, test.b and test.c and do it within the same single Maven project.

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

To do this we will need three separate executions of the maven-jaxb2-plugin, each configured with its own schema and target package. For example:

        <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.xsd 的类将在 test.atest.b 中生成,这是我们想要避免的.

OK, this would create three target directories with three target packages. Next problem is that classes from c.xsd will generated in test.a and test.b which we want to avoid.

为了实现这一点,我们必须告诉 XJC 使用 test.c 中的类来处理 c.xsd 中的类型.这实际上是 episode 文件的用途.此文件通常在 META-INFsun-jaxb.episode 下生成,它包含已处理模式中所有类型的绑定.这是为 c.xsd 生成的示例:

To achieve this, we have to tell XJC to use classes from test.c for types from c.xsd. This is actually what episode file is for. This file is normally generated under META-INFsun-jaxb.episode and it contains bindings for all types in the processed schema. Here's an example generated for 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>

剧集文件实际上是一个普通的绑定文件.所以可以直接在编译中使用:

Episode file is actually a normal bindings file. So you can directly use it in compilation:

                <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>

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

There is just one tiny problem left. Episode files generated by XJC also contain this fragment:

    <schemaBindings map="false">
      <!-- ... -->
    </schemaBindings>

它实际上是说不要为给定命名空间中的模式生成代码".如果 a.xsdb.xsd 位于不同的命名空间中,这将不是问题.但是由于它们在同一个命名空间中,这个片段将有效地关闭 a.xsdb.xsd 的所有代码生成.

It effectively says "do not generate code for schema in the given namespace". This would not be a problem if a.xsd or b.xsd would be in a different namespace. But since they are in the same namespace, this fragment will effectively turn off all code generation for a.xsd or b.xsd.

要解决这个问题,我们可以对为 c.xsd 生成的 sun-jaxb.episode 进行后处理.这可以通过一个简单的 XSLT 来完成:

To work around this we can post-process the sun-jaxb.episode which was generated for c.xsd. This can be done with a simple 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>

此 XSLT 应该在 c.xsd 的代码之后运行,但在 a.xsdb.xsd 的代码之前运行生成.这可以通过将这些执行放入不同的阶段(generate-sourcesprocess-sourcesgenerate-resources)来实现.

This XSLT should be run after the code for c.xsd, but before the code for a.xsd and b.xsd is generated. This can be achieved by putting these executions into different phases (generate-sources, process-sources, generate-resources).

下面是完整的pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.jvnet.jaxb2.maven2</groupId>
    <artifactId>divide</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>2.2.11</version>
        </dependency>
        <!-- JUnit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
            <version>4.12</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>xml-maven-plugin</artifactId>
                <version>1.0.2</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>transform</goal>
                        </goals>
                        <phase>process-sources</phase>
                    </execution>
                </executions>
                <configuration>
                    <transformationSets>
                        <transformationSet>
                            <dir>${project.build.directory}/xjc-c/META-INF</dir>
                            <outputDir>${project.build.directory}/xjc-c/META-INF</outputDir>
                            <includes>
                                <include>sun-jaxb.episode</include>
                            </includes>
                            <stylesheet>src/main/xslt/removeJaxbSchemaBindings.xslt</stylesheet>
                        </transformationSet>
                    </transformationSets>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.jvnet.jaxb2.maven2</groupId>
                <artifactId>maven-jaxb2-plugin</artifactId>
                <version>0.13.3</version>
                <executions>
                    <execution>
                        <id>xjc-c</id>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <phase>generate-sources</phase>
                        <configuration>
                            <generatePackage>test.c</generatePackage>
                            <generateDirectory>${project.build.directory}/xjc-c</generateDirectory>
                            <schemaIncludes>
                                <includes>c.xsd</includes>
                            </schemaIncludes>
                        </configuration>
                    </execution>
                    <execution>
                        <id>xjc-a</id>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <phase>generate-resources</phase>
                        <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>
                    <execution>
                        <id>xjc-b</id>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <phase>generate-resources</phase>
                        <configuration>
                            <generatePackage>test.b</generatePackage>
                            <generateDirectory>${project.build.directory}/xjc-b</generateDirectory>
                            <schemaIncludes>
                                <includes>b.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>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

这篇关于maven-jaxb2-plugin 在同一项目中重用公共 XSD的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆