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

查看:87
本文介绍了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的执行中引用此剧集/绑定文件? 使用剧集仅提及如何从中引用剧集文件其他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生成了三次相同的类。

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.

推荐答案

免责声明:我是 maven-jaxb2-插件

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.xsd b.xsd c.xsd 位于同一名称空间中, a.xsd b.xsd 无法导入 c.xsd ,他们只能包含它。我们想要将每个XSD生成到它自己的包中,例如 test.a test.b test.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.a 测试中生成。 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 的类型。这实际上是剧集文件的用途。此文件通常在 META-INF \sun-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-INF\sun-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.xsd b.xsd 将位于不同的命名空间中,这将不会成为问题。但由于它们位于相同的命名空间中,因此该片段将有效地关闭 a.xsd b.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.

要解决此问题,我们可以对为生成的 sun-jaxb.episode 进行后处理 c.xsd 。这可以通过一个简单的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.xsd b.xsd 的代码之前。这可以通过将这些执行分为不同的阶段来实现( generate-sources process-sources generate-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天全站免登陆