Создание классов Java из XMLSchema.xsd с использованием JAXB

Я использую jaxb для генерации классов java из схемы xml. Схема импортирует XMLSchema.xsd, а ее содержимое используется как элемент в документе.

Если я удалю импорт и ссылку на "xsd: schema" соответственно, то компилятор привязки успешно завершит классы. Если я этого не сделаю, это приведет к следующим ошибкам, которые будут одинаковыми, если я попытаюсь создать классы Java только из XMLSchema.xsd!

>  C:\Users\me>"%JAXB%/xjc" -extension -d tmp/uisocketdesc -p uis.jaxb uisocketdesc.xsd -b xml_binding_test.xml -b xml_binding_test_2.xml
-b xml_binding_test_3.xml
parsing a schema...
compiling a schema...

> [ERROR] A class/interface with the same name "uis.jaxb.ComplexType" is already in use. Use a class customization to resolve this conflict.
 line 612 of "http://www.w3.org/2001/XMLSchema.xsd"

> [ERROR] (Relevant to above error) another "ComplexType" is generated from here.
 line 440 of "http://www.w3.org/2001/XMLSchema.xsd"

> [ERROR] A class/interface with the same name "uis.jaxb.Attribute" is already in use. Use a class customization to resolve this conflict.
 line 364 of "http://www.w3.org/2001/XMLSchema.xsd"

> [ERROR] (Relevant to above error) another "Attribute" is generated from here.
 line 1020 of "http://www.w3.org/2001/XMLSchema.xsd"

> [ERROR] A class/interface with the same name "uis.jaxb.SimpleType" is already in use. Use a class customization to resolve this conflict.
 line 2278 of "http://www.w3.org/2001/XMLSchema.xsd"

> [ERROR] (Relevant to above error) another "SimpleType" is generated from here.
 line 2222 of "http://www.w3.org/2001/XMLSchema.xsd"

> [ERROR] A class/interface with the same name "uis.jaxb.Group" is already in use. Use a class customization to resolve this conflict.
 line 930 of "http://www.w3.org/2001/XMLSchema.xsd"

> [ERROR] (Relevant to above error) another "Group" is generated from here.
 line 727 of "http://www.w3.org/2001/XMLSchema.xsd"

> [ERROR] A class/interface with the same name "uis.jaxb.AttributeGroup" is already in use. Use a class customization to resolve this conflict.
 line 1062 of "http://www.w3.org/2001/XMLSchema.xsd"

> [ERROR] (Relevant to above error) another "AttributeGroup" is generated from here.
 line 1026 of "http://www.w3.org/2001/XMLSchema.xsd"

> [ERROR] A class/interface with the same name "uis.jaxb.Element" is already in use. Use a class customization to resolve this conflict.
 line 721 of "http://www.w3.org/2001/XMLSchema.xsd"

> [ERROR] (Relevant to above error) another "Element" is generated from here.
 line 647 of "http://www.w3.org/2001/XMLSchema.xsd"

> [ERROR] Two declarations cause a collision in the ObjectFactory class.
 line 1020 of "http://www.w3.org/2001/XMLSchema.xsd"

> [ERROR] (Related to above error) This is the other declaration.
 line 364 of "http://www.w3.org/2001/XMLSchema.xsd"

> [ERROR] Two declarations cause a collision in the ObjectFactory class.
 line 2278 of "http://www.w3.org/2001/XMLSchema.xsd"

> [ERROR] (Related to above error) This is the other declaration.
 line 2222 of "http://www.w3.org/2001/XMLSchema.xsd"

> [ERROR] Two declarations cause a collision in the ObjectFactory class.
 line 930 of "http://www.w3.org/2001/XMLSchema.xsd"

> [ERROR] (Related to above error) This is the other declaration.
 line 727 of "http://www.w3.org/2001/XMLSchema.xsd"

> [ERROR] Two declarations cause a collision in the ObjectFactory class.
 line 440 of "http://www.w3.org/2001/XMLSchema.xsd"

> [ERROR] (Related to above error) This is the other declaration.
 line 612 of "http://www.w3.org/2001/XMLSchema.xsd"

> [ERROR] Two declarations cause a collision in the ObjectFactory class.
 line 1026 of "http://www.w3.org/2001/XMLSchema.xsd"

> [ERROR] (Related to above error) This is the other declaration.
 line 1062 of "http://www.w3.org/2001/XMLSchema.xsd"

> [ERROR] Two declarations cause a collision in the ObjectFactory class.
 line 647 of "http://www.w3.org/2001/XMLSchema.xsd"

> [ERROR] (Related to above error) This is the other declaration.
 line 721 of "http://www.w3.org/2001/XMLSchema.xsd"

Failed to produce code.

Ответ 1

Борясь с такими вещами, для меня это проблема чувствительности к регистру и одно и то же имя для проблемы с элементами и атрибутами (иногда с наследованием). Для второй проблемы я использую внешний файл привязки, который содержит что-то вроде этого:

<jaxb:bindings node="//xs:complexType[@name='AbstractGriddedSurfaceType']//xs:attribute[@name='rows']">
    <jaxb:property name="rowCount"/>
</jaxb:bindings>

Для проблем с чувствительностью к регистру вы можете использовать аргумент xjc -XautoNameResolution, версия maven - <args><arg>-B-XautoNameResolution</arg></args>, но это не работает для элементов оболочки, поэтому для этого вам нужно написать настройки jaxb как упомянутый выше,... и если вам не повезло, как мне:), вам может понадобиться использовать локальную копию xsd и исправить дублирование вручную.

Edit Нашел другое решение для проблемы чувствительности к регистру, когда переименование имени элемента недостаточно:

<jaxb:bindings node=".//xs:element[@name='imageDatum'][@type='gml:ImageDatumPropertyType']">
    <jaxb:property name="imageDatumInst"/>
    <jaxb:factoryMethod name="imageDatumInst" />
</jaxb:bindings>

Удачи, надеюсь, что это поможет.

Ответ 2

Вы можете успешно получить JAXB для генерации кода для XML-схемы xsd (по крайней мере) двумя способами. Проблема, с которой вы столкнулись, связана с тем, что некоторые типы и элементы схемы имеют одинаковые имена.


Первый вариант позволяет избежать конфликтов имен, применяя одно или несколько преобразований имен XML к сгенерированным именам классов. Ниже приведен пример внешнего файла привязки, который будет делать это:

<jxb:bindings version="2.1"
               xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
               xmlns:xs="http://www.w3.org/2001/XMLSchema"
               xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
               jxb:extensionBindingPrefixes="xjc">  
  <jxb:globalBindings>
    <xjc:simple/>   
  </jxb:globalBindings>   
  <jxb:bindings schemaLocation="XMLSchema.xsd">
    <jxb:schemaBindings>
      <jxb:nameXmlTransform>
        <jxb:elementName suffix="Element"/>
      </jxb:nameXmlTransform>
    </jxb:schemaBindings>
  </jxb:bindings>  
</jxb:bindings>

Этот подход работает (вы можете применять другие преобразования, которые будут работать так же хорошо, но я видел эту технику снова и снова в документации), но я думаю, что это приводит к уродливым результатам. Например, в этом случае создается сгенерированный класс с именем ElementElement.


Второй подход использует настройку класса, как предложено выводом xjc. Фактически, все, кроме одного из классов проблем, имеют свойство abstract="true", заданное в соответствующем типе схемы. Поэтому мне представляется целесообразным добавить имя класса к "Абстрактному", т.е. AbstractElement. Оставшийся класс Attribute не является абстрактным, но xs:element с именем Attribute создает класс расширения с пустым телом. Поэтому я назвал его BaseAttribute. Вот определение внешней привязки, которое я использовал:

<jxb:bindings version="2.1"
               xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
               xmlns:xs="http://www.w3.org/2001/XMLSchema"
               xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
               jxb:extensionBindingPrefixes="xjc">
  <jxb:globalBindings>
    <xjc:simple/>
  </jxb:globalBindings>
  <jxb:bindings schemaLocation="XMLSchema.xsd">
    <jxb:schemaBindings>
      <jxb:package name="org.w3.xmlschema"/>
    </jxb:schemaBindings>
    <jxb:bindings node="//xs:complexType[@name='complexType']">
      <jxb:class name="AbstractComplexType"/>
    </jxb:bindings> 
    <jxb:bindings node="//xs:complexType[@name='group']">
      <jxb:class name="AbstractGroup"/>
    </jxb:bindings> 
    <jxb:bindings node="//xs:complexType[@name='attributeGroup']">
      <jxb:class name="AbstractAttributeGroup"/>
    </jxb:bindings> 
    <jxb:bindings node="//xs:complexType[@name='simpleType']">
      <jxb:class name="AbstractSimpleType"/>
    </jxb:bindings> 
    <jxb:bindings node="//xs:complexType[@name='element']">
      <jxb:class name="AbstractElement"/>
    </jxb:bindings> 
    <jxb:bindings node="//xs:complexType[@name='attribute']">
      <jxb:class name="BaseAttribute"/>
    </jxb:bindings> 
  </jxb:bindings>
</jxb:bindings>

Это дает более ясные имена классов, на мой взгляд, и успешно компилирует схему.


Я также рекомендовал бы использовать отдельную компиляцию для XMLSchema.xsd и хранить ее в файле jar для последующего использования, если эта проблема возникла снова при компиляции другой схемы. Ответы на этот вопрос описывают как.

Ответ 3

Похоже, ваша схема сломана. XJC чрезвычайно придирчив к этим вещам и может потерпеть неудачу в вещах, которые пропускают другие инструменты.

Вместо того, чтобы выбирать ошибки XJC, мне легче запустить схему с помощью AlphaWorks Schema Quality Checker. Это дает хороший, удобочитаемый (хорошо, понятный для разработчиков, в любом случае) вывод о том, что неправильно. Если это пройдет через это ОК, у вас будет гораздо больше шансов получить его через XJC.

Ответ 4

У меня возникла такая же проблема при создании объектов из .wsdl с помощью cxf. Резолюция для меня заключается в использовании -autoNameResolution в качестве сообщения об ошибке. Конфигурация Maven:

         <wsdlOption>
                            <wsdl>${basedir}/test.wsdl</wsdl>
                            <extraargs>
                                <extraarg>-b</extraarg>     
                            <extraarg>http://www.w3.org/2001/XMLSchema.xsd</extraarg>
                                <extraarg>-autoNameResolution</extraarg>
                            </extraargs>
                            <packagenames>
                                <packagename>test.wsdl</packagename>
                            </packagenames>
                        </wsdlOption>

Ответ 5

Другой вариант - удалить параметр -p, чтобы классы были сгенерированы в разных пакетах.

Ответ 6

Я пробовал следовать, и это сработало для меня:

<jxb:bindings schemaLocation="ClaimActivity-ACORD.xsd">
    <jxb:schemaBindings>
        <jxb:package name="x.x.x.x" />
    </jxb:schemaBindings>
    <jxb:bindings node="//xsd:complexType[@name='ConstructionType']">
        <jxb:class name="AbstractConstructionType" />
    </jxb:bindings>
    <jxb:bindings node="//xsd:complexType[@name='ItemDefinitionType']">
        <jxb:class name="AbstractItemDefinitionType" />
    </jxb:bindings>
    <jxb:bindings node="//xsd:complexType[@name='LocationType']">
        <jxb:class name="AbstractLocationType" />
    </jxb:bindings>
    <jxb:bindings node="//xsd:complexType[@name='TaxFeeType']">
        <jxb:class name="AbstractTaxFeeType" />
    </jxb:bindings>
    <jxb:bindings node="//xsd:complexType[@name='DeductibleType']">
        <jxb:class name="AbstractDeductibleType" />
    </jxb:bindings>
    <jxb:bindings node="//xsd:complexType[@name='RegistrationType']">
        <jxb:class name="AbstractRegistrationType" />
    </jxb:bindings>
</jxb:bindings>

Ответ 7

Вы можете использовать xjc, который поставляется с JDK1.6. Также вы можете попробовать XML для Java, обратитесь к этой статье.