如何解决JAXB2 Maven Plugin生成代码时的XSD元素重复定义问题?
解决同名XSD元素冲突的Java代码生成方案
问题本质是两份XSD共享同一个targetNamespace,且都定义了全局元素<content>,违反XML Schema规范,导致XJC编译报错。以下是三种无需修改原XSD的可行方案:
方案一:独立编译每个XSD,指定不同包/输出目录
将两个XSD分开编译,生成到不同的Java包或目录下,避免类名冲突。修改Maven插件配置如下:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>jaxb2-maven-plugin</artifactId> <version>3.1.0</version> <executions> <!-- 编译first.xsd到指定包 --> <execution> <id>generate-first-xsd</id> <goals> <goal>xjc</goal> </goals> <configuration> <sources> <source>src/main/resources/integration/first.xsd</source> </sources> <packageName>com.example.online.first</packageName> <outputDirectory>${project.build.directory}/generated-sources/first</outputDirectory> </configuration> </execution> <!-- 编译second.xsd到另一个包 --> <execution> <id>generate-second-xsd</id> <goals> <goal>xjc</goal> </goals> <configuration> <sources> <source>src/main/resources/integration/second.xsd</source> </sources> <packageName>com.example.online.second</packageName> <outputDirectory>${project.build.directory}/generated-sources/second</outputDirectory> </configuration> </execution> </executions> </plugin>
编译后,两份XSD的content元素会分别生成com.example.online.first.Content和com.example.online.second.Content,互不冲突。
方案二:使用绑定文件重命名冲突元素
创建JAXB绑定文件,指定其中一个XSD的<content>生成自定义类名,避免类名重复。
- 创建
src/main/resources/integration/binding.xml:
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.1"> <!-- 为second.xsd的content元素指定生成类名 --> <jaxb:bindings schemaLocation="src/main/resources/integration/second.xsd"> <jaxb:bindings node="//xs:element[@name='content']"> <jaxb:class name="TransactionContent"/> </jaxb:bindings> </jaxb:bindings> </jaxb:bindings>
- 修改Maven插件配置引入绑定文件:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>jaxb2-maven-plugin</artifactId> <version>3.1.0</version> <configuration> <outputDirectory>${project.build.directory}/generated-sources/</outputDirectory> <bindingDirectory>src/main/resources/integration</bindingDirectory> <bindings> <binding>binding.xml</binding> </bindings> </configuration> <executions> <execution> <id>generate-source-code</id> <goals> <goal>xjc</goal> </goals> <configuration> <sources> <source>src/main/resources/integration/first.xsd</source> <source>src/main/resources/integration/second.xsd</source> </sources> </configuration> </execution> </executions> </plugin>
编译后,first.xsd生成Content类,second.xsd生成TransactionContent类,解决冲突。
方案三:用Catalog重定向命名空间
通过XML Catalog将其中一个XSD的目标命名空间映射到新地址,让两份XSD属于不同命名空间,避免元素冲突。
- 创建
src/main/resources/integration/catalog.xml:
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog"> <!-- 将second.xsd的原命名空间重定向到新命名空间 --> <rewriteURI uriStartString="http://example/data/online" rewritePrefix="http://example/data/online/transaction"/> </catalog>
- 修改Maven插件配置指定Catalog文件:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>jaxb2-maven-plugin</artifactId> <version>3.1.0</version> <configuration> <outputDirectory>${project.build.directory}/generated-sources/</outputDirectory> <catalog>src/main/resources/integration/catalog.xml</catalog> </configuration> <executions> <execution> <id>generate-source-code</id> <goals> <goal>xjc</goal> </goals> <configuration> <sources> <source>src/main/resources/integration/first.xsd</source> <source>src/main/resources/integration/second.xsd</source> </sources> </configuration> </execution> </executions> </plugin>
编译后,second.xsd的代码会生成到对应新命名空间的Java包下,与first.xsd的代码无冲突。
内容的提问来源于stack exchange,提问作者Andy
相关产品推荐
相关产品推荐

