Создание классов 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, обратитесь к этой статье.