Amazon Product.xsd的JAXB类生成无法正常工作

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Amazon Product.xsd的JAXB类生成无法正常工作相关的知识,希望对你有一定的参考价值。

使用JAXB和maven插件从Products.xsd生成Java类时,我收到以下警告和错误

org.xml.sax.SAXParseException; systemId: https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/amzn-base.xsd; lineNumber: 956; columnNumber: 45; Simple type "ProcessorTypeValues" was not mapped to Enum due to EnumMemberSizeCap limit. Facets count: 744, current limit: 256. You can use customization attribute "typesafeEnumMaxMembers" to extend the limit.
  at com.sun.tools.xjc.reader.xmlschema.ErrorReporter.warning(ErrorReporter.java:88)
...
Error while generating code.Location [ https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/SWVG.xsd{300,40}].
  org.xml.sax.SAXParseException; systemId: https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/SWVG.xsd; lineNumber: 300; columnNumber: 40; A class/interface with the same name "generated.BBFCRatingType" is already in use. Use a class customization to resolve this conflict.

在我能够解决这个问题之后,我得到了如下错误:

.../target/generated-sources/xjc/generated/Home.java:[2737,45] cannot find symbol
  symbol:   class Home
  location: class generated.Home.ProductType
.../target/generated-sources/xjc/generated/Home.java:[2929,23] class generated.Home is already defined in package generated

我在google搜索时看到了很多关于这方面的问题,但是没有人提出适当的解决方案。

答案

经过一天的分析问题并逐步解决问题后,我开始工作了。

我认为XSD不是很一致,它们包含多个元素声明,可以在一个普通的XSD中进行总结,一些元素的层次结构包含同名的元素。

在使用JAXB默认设置时,XSD无效,但在某些方面不符合Java约定。

一种解决方案是,将XSD保持在本地并仅注释掉冲突的部分,然后生成类。但我想使用提供的URL生成类,所以这对我不起作用。

所以我会在这里发布我的解决方案,也许它可以帮助某人:

生成是通过pom.xml中的maven-jaxb2-plugin完成的,所以这部分读取(我的目标包被定义为com.amazon.product,你可以把它改成你喜欢的):

<plugins>
...
 <plugin>
    <groupId>org.jvnet.jaxb2.maven2</groupId>
    <artifactId>maven-jaxb2-plugin</artifactId>
    <version>0.8.1</version>
    <executions>
      <execution>
        <goals>
          <goal>generate</goal>
        </goals>
        <configuration>
          <schemas>
            <schema>
              <url>https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/Product.xsd</url>
            </schema>
          </schemas>
        </configuration>
        <id>jaxb-generate-amazon</id>
      </execution>
    </executions>
    <configuration>
      <catalogResolver>org.jvnet.jaxb2.maven2.resolver.tools.ClasspathCatalogResolver</catalogResolver>
      <generatePackage>com.amazon.product</generatePackage>
      <generateDirectory>${project.build.directory}/generated-sources/xjc</generateDirectory>
      <verbose>true</verbose>
      <removeOldOutput>false</removeOldOutput>
      <clearOutputDir>false</clearOutputDir>
      <forceRegenerate>true</forceRegenerate>
    </configuration>
 </plugin>
...
<plugins>

我在资源文件夹中的bindig.xjb读取:

  <bindings
    xmlns="http://java.sun.com/xml/ns/jaxb" 
    xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    version="2.1">

  <globalBindings underscoreBinding="asCharInWord" typesafeEnumMaxMembers="9000" typesafeEnumMemberName="generateName"/>

  <bindings schemaLocation="https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/FoodServiceAndJanSan.xsd" node="//xsd:element[@name='ProductType']/xsd:complexType/xsd:choice/xsd:element[@name='FoodServiceAndJanSan']/xsd:complexType">
    <class name="FoodServiceAndJanSanSub"/>
  </bindings>
  <bindings schemaLocation="https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/Home.xsd" node="//xsd:element[@name='ProductType']/xsd:complexType/xsd:choice/xsd:element[@name='Home']/xsd:complexType">
    <class name="HomeSub"/>
  </bindings>
  <bindings schemaLocation="https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/GiftCards.xsd" node="//xsd:element[@name='ProductType']/xsd:complexType/xsd:choice/xsd:element[@name='GiftCard']/xsd:complexType">
    <class name="GiftCardSub"/>
  </bindings>
  <bindings schemaLocation="https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/MechanicalFasteners.xsd" node="//xsd:element[@name='ProductType']/xsd:complexType/xsd:choice/xsd:element[@name='MechanicalFasteners']/xsd:complexType">
    <class name="MechanicalFastenersSub"/>
  </bindings>
</bindings>

为什么我们需要这种绑定?我会告诉你:

长枚举类型会导致警告

这只是一个警告,但它让我恼火。诸如'ProcessorTypeValues`之类的枚举具有比默认有效数256更多的条目。您可以在globalBindings中配置它:

<globalBindings ... typesafeEnumMaxMembers="1000" .../>

具有相同名称“generated.BBFCRatingType”的类/接口已在使用中。

例如,亚马逊定义了BBFCRatingTypeBBFC_Rating_Type等元素类型。不幸的是,默认配置将为名为BBFCRatingType的Java类生成。但是Java包中的两个类不能具有相同的名称。解决方案是告诉JAXB包含下划线:

<globalBindings ... underscoreBinding="asCharInWord" .../>

class generated.Home已经在包生成中定义

例如,Home.xsd将一个名为Home的元素定义为ProductType的子元素,Home本身位于另一个元素中,也称为<bindings schemaLocation="https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/Home.xsd" node="//xsd:element[@name='ProductType']/xsd:complexType/xsd:choice/xsd:element[@name='Home']/xsd:complexType"> <class name="HomeSub"/> </bindings> 。问题与之前的错误相同:在一个包中具有相同名称的两个类。

我们必须给第二个类别一个不同的名字:

<bindings schemaLocation="xsd/ProductClothing.xsd">
  <bindings node="//xsd:element[@name='VariationData']/xsd:complexType/xsd:sequence">
    <bindings node="./xsd:element[@name='Parentage']/xsd:simpleType">
      <typesafeEnumClass name="Parentage" />
    </bindings>
    <bindings node="./xsd:element[@name='VariationTheme']/xsd:simpleType">
      <typesafeEnumClass name="VariationTheme" />
    </bindings>
  </bindings>
  <bindings node="//xsd:element[@name='ClassificationData']/xsd:complexType/xsd:sequence">
    <bindings node="./xsd:element[@name='ClothingType']/xsd:simpleType">
      <typesafeEnumClass name="ClothingType" />
    </bindings>
    <bindings node="./xsd:element[@name='PerformanceRating']/xsd:simpleType">
      <typesafeEnumClass name="PerformanceRating" />
    </bindings>
    <bindings node="./xsd:element[@name='CupSize']/xsd:simpleType">
      <typesafeEnumClass name="CupSize" />
    </bindings>
    <bindings node="./xsd:element[@name='TargetGender']/xsd:simpleType">
      <typesafeEnumClass name="TargetGender" />
    </bindings>
    <bindings node="./xsd:element[@name='WaterResistanceLevel']/xsd:simpleType">
      <typesafeEnumClass name="WaterResistanceLevel" />
    </bindings>
  </bindings>
</bindings>

额外的想法/改进

如果你想要一些不能自动生成的枚举,要成为真正的Java枚举,你必须为每个枚举手动强制它。例如,对于ProductClothing:

repository on GitHub

更新于22.12.2017

我创建了一个包含所有必要绑定的qazxswpoi,以使XSD与Java一起工作。

以上是关于Amazon Product.xsd的JAXB类生成无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

如何克隆JAXB对象

JAXB - The JAXB Context

JAXB - 属性“值”已定义。使用 <jaxb:property> 解决此冲突

JAXB实现java对象与xml之间转换

JAXB简单样例

JAXP 和 JAXB 有啥区别?