当两个单独的模式具有相同的命名空间时,如何告诉 JAXB 在单独的包中生成类?

问题描述 投票:0回答:2

我怀疑对此没有好的答案,但希望我遗漏了一些东西。假设我有两个独立的 XML 模式,它们都具有相同的命名空间,定义了一些重复的复杂类型,并且我想使用 JAXB 为它们生成 Java 类。作为一个非常简单的例子:

schema1.xsd:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema elementFormDefault="qualified" targetNamespace="namespace1" xmlns="namespace1" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="foo" type="xs:string"/>
</xs:schema>

schema2.xsd:(与上面相同)

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema elementFormDefault="qualified" targetNamespace="namespace1" xmlns="namespace1" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="foo" type="xs:string"/>
</xs:schema>

当我尝试使用 JAXB(通过 gradle 的 Ant XJC 任务)生成这些内容时,我收到以下完全合理的错误:

[ant:xjc] [ERROR] 'foo' is already defined
[ant:xjc]   line 3 of file:/C:/dev/test/src/main/resources/schema2.xsd
[ant:xjc]
[ant:xjc] [ERROR] (related to above error) the first definition appears here
[ant:xjc]   line 3 of file:/C:/dev/test/src/main/resources/schema1.xsd

根据 JAXB 文档,我尝试在外部自定义文件中指定包,如下所示:

<jaxb:bindings schemaLocation="schema1.xsd">
    <jaxb:schemaBindings>
        <jaxb:package name="package1"/>
    </jaxb:schemaBindings>
</jaxb:bindings>
<jaxb:bindings schemaLocation="schema2.xsd">
    <jaxb:schemaBindings>
        <jaxb:package name="package2"/>
    </jaxb:schemaBindings>
</jaxb:bindings>

但这不起作用 - 然后我意识到上面链接的相同文档说:

请注意,此自定义是针对每个命名空间的。也就是说,即使您的架构被拆分为多个架构文档,如果它们都位于同一命名空间中,您也不能将它们放入不同的包中。

所以,我猜这永远不会起作用。

有什么明智的方法吗?我怀疑正确的答案是模式应该位于不同的命名空间中,因为这可以解决问题,并且可能更具逻辑意义,但我对模式没有任何控制权 - 它们是由第三方提供的。我问过是否可以更改它们,但我怀疑答案是否定的。

我能看到的唯一其他选项是生成 Java 类两次,首先为 schema1.xsd,然后单独为 schema2.xsd,每次都使用自己的自定义文件指定不同的包,但这感觉像是一个非常笨拙的解决方案。我还缺少更明智的选择吗?

java xml xsd namespaces jaxb
2个回答
2
投票

你不能。包是根据命名空间生成的。相同的命名空间 - 相同的包。

在这种情况下你必须执行多次。还要注意使用不同的输出生成目录(如

target/generated-sources/xjc1
target/generated-sources/xjc2
),否则“仅在发生任何更改时才编译”将无法正常工作。


0
投票

lexcore 是对的,如果你想从同一个 XML 命名空间为不同的 Java 包生成类,你必须使用多次执行。

您可能会在

schema1.xsd
schema2.xsd
中使用相同的 XML 类型,例如,将一些
common.xsd
包含到
schema1.xsd
schema2.xsd
中。如果您只运行两次执行,您将在
package1
package2
中重复这些常见类型。

您可以使用以下方法避免此类重复。

该方法已通过

maven-jaxb-plugin
版本
3.1.0
进行测试。

你必须制作4个XJB文件:

  • common.xjb
    common-classes.xjb
    为常见类型
  • schema1.xjb
    适用于
    schema1.xsd
  • 的特定类型
  • schema2.xjb
    适用于
    schema2.xsd
  • 的特定类型

common.xjb
将常用类型放入
common
Java 包中:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<bindings version="3.0" xmlns="https://jakarta.ee/xml/ns/jaxb">
  <bindings scd="x-schema::tns" xmlns:tns="https://namespace1">
    <schemaBindings>
      <package name="common"/>
    </schemaBindings>
  </bindings>
</bindings>

common-classes.xjb
将指示
schema1
schema2
重用
common
Java 包中的常见类型:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<bindings version="3.0" xmlns="https://jakarta.ee/xml/ns/jaxb">
  <bindings scd="x-schema::tns" xmlns:tns="https://namespace1">
    <bindings scd="~tns:CommonType1">
      <class ref="common.CommonType1"/>
    </bindings>
    <bindings scd="~tns:CommonType2">
      <class ref="common.CommonType2"/>
    </bindings>
    <!-- ... -->
  </bindings>
</bindings>

请注意,

maven-jaxb-plugin
可以通过在
common-classes.xjb
上执行来为您生成大部分
common.xsd
文件。执行后查看
target/classes/META-INF/JAXB
目录。

schema1.xjb
会将
schema1.xsd
特定类型放入
package1
:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<bindings version="3.0" xmlns="https://jakarta.ee/xml/ns/jaxb">
  <bindings scd="x-schema::tns" xmlns:tns="https://namespace1">
    <schemaBindings>
      <package name="package1"/>
    </schemaBindings>
  </bindings>
</bindings>

schema2.xjb
会将
schema2.xsd
特定类型放入
package2
:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<bindings version="3.0" xmlns="https://jakarta.ee/xml/ns/jaxb">
  <bindings scd="x-schema::tns" xmlns:tns="https://namespace1">
    <schemaBindings>
      <package name="package2"/>
    </schemaBindings>
  </bindings>
</bindings>

最后,您必须在

maven-jaxb-plugin
中定义 3 个
pom.xml
执行:

  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>jaxb2-maven-plugin</artifactId>
        <version>3.1.0</version>

        <!-- Common configuration for all executions -->
        <configuration>
          <clearOutputDir>false</clearOutputDir>
        </configuration>

        <executions>
          <execution>
            <id>xjc-common</id>
            <goals>
              <goal>xjc</goal>
            </goals>
            <configuration>
              <sources>
                <source>common.xsd</source>
              </sources>
              <xjbSources>
                <xjbSource>common.xjb</xjbSource>
              </xjbSources>
            </configuration>
          </execution>

          <execution>
            <id>xjc-schema1</id>
            <goals>
              <goal>xjc</goal>
            </goals>
            <configuration>
              <sources>
                <source>schema1.xsd</source>
              </sources>
              <xjbSources>
                <xjbSource>common-classes.xjb</xjbSource>
                <xjbSource>schema1.xjb</xjbSource>
              </xjbSources>
            </configuration>
          </execution>

          <execution>
            <id>xjc-schema2</id>
            <goals>
              <goal>xjc</goal>
            </goals>
            <configuration>
              <sources>
                <source>schema2.xsd</source>
              </sources>
              <xjbSources>
                <xjbSource>common-classes.xjb</xjbSource>
                <xjbSource>schema2.xjb</xjbSource>
              </xjbSources>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
© www.soinside.com 2019 - 2024. All rights reserved.