how to create common xsd generated java classes

a 夏天 提交于 2019-12-02 11:58:55

Do separate - aka modular - schema compilation using so-called episodes. That is to say, if you want to import schema A into schema B and generate classes for schema B, you first create a separate Maven project in order to compile schema A to a separate Maven artifact with maven-jaxb2-plugin as usual. (This is assuming the schema A stands alone, i.e. does not import any other schema; else you have to repeat the same process on the imported schema(s).) As a result, you get A.jar with the generated classes only from schema A, and most importantly, a META-INF/sun-jaxb.episode file. This file provides information about the existing XSD-to-Java bindings, and this will tell the maven-jaxb2-plugin (in fact the xjc tool underlying maven-jaxb2-plugin) what has already been generated from the schema, and therefore prevent it to re-generate the same classes again.

Then you create another Maven project in order to compile schema B, with maven artifact of A.jar among its Maven dependencies. This time, in the configuration of maven-jaxb2-plugin, you set the configuration parameter useDependenciesAsEpisodes to true. This will tell the plugin to use the .episode files from all dependencies (when there is any). You can find a basic example on the plugin's GitHub wiki. Below is a real-life example from AuthzForce project, an XACML implementation, where the OASIS XACML standard schema (xacml-core-v3-schema-wd-17.xsd) imports the W3C standard XML namespace schema (xml.xsd). Therefore, you have one Maven project/artifact for the xml.xsd, and another one for the XACML schema, where the relevant parts of the POM look like this:

<project ...>
  ...
  <dependencies>
    ...
    <dependency>
        <groupId>${project.groupId}</groupId>
        <artifactId>${artifactId.prefix}-xmlns-model</artifactId>
        <version>${project.parent.version}</version>
    </dependency>
    ...
  </dependencies>
  <build>
    <plugins>
        ...
        <plugin>
            <groupId>org.jvnet.jaxb2.maven2</groupId>
            <artifactId>maven-jaxb2-plugin</artifactId>
            <configuration>
                <verbose>true</verbose>
                <extension>true</extension>
                <strict>false</strict>
                <useDependenciesAsEpisodes>true</useDependenciesAsEpisodes>
                ...
                <catalog>src/main/jaxb/catalog.xml</catalog>
                <schemaDirectory>src/main/resources</schemaDirectory>
                <schemaIncludes>
                    <include>xacml-core-v3-schema-wd-17.xsd</include>
                </schemaIncludes>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
  </build>
</project>

You notice that there is also a catalog parameter pointing to the XML catalog file. This is also important because this catalog will enable the plugin to locate the A.xsd file (xml.xsd in my example) directly in its maven artifact, so that you don't need to duplicate the file in project B or elsewhere. In my example, since the XACML schema imports xml.xsd as follows:

<xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd"/>

... the catalog.xml must look like this:

<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
  <system systemId="http://www.w3.org/2001/xml.xsd" uri="maven:org.ow2.authzforce:authzforce-ce-xmlns-model:jar!/xml.xsd" />
</catalog>

You notice that the uri parameter references the xml.xsd from its Maven artifact. For more info on this syntax to refer to Maven artifact resources, refer to the maven-jaxb2-plugin's wiki.

In general, to allow maximum flexibility and simplicity in managing schema locations, I recommend to specify only the namespace in schema imports. (No schemaLocation.) For example, prefer this:

<xs:import namespace="http://www.w3.org/XML/1998/namespace" />

... in which case the catalog.xml should look like this:

<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
  <public publicId="http://www.w3.org/XML/1998/namespace" uri="maven:org.ow2.authzforce:authzforce-ce-xmlns-model:jar!/xml.xsd" />
</catalog>

(This is not the case in my example exceptionally, because the official XACML schema from the standard committee uses a schemaLocation, so it's preferable to keep it as is like the original.)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!