Как сгенерировать классы @XmlRootElement для базовых типов в XSD?

У меня возникли проблемы с созданием классов Java с соответствующими аннотациями JAXB из XSD с использованием XJC.

У меня есть относительно простой файл XSD, определяющий мою схему XML. Сложные типы в XSD используют наследование с помощью тегов <xs:extension>. Проблема, с которой я столкнулся, заключается в том, что мне нужны все сложные типы для создания классов Java с @XmlRootElement.

К сожалению, способ, которым XJC генерирует классы, означает, что только производный класс получает @XmlRootElement (а не базовый класс). Я использую простую директиву глобальной привязки, чтобы гарантировать, что она решает многие другие проблемы, с которыми я столкнулся с XJC.

Вот пример фрагмента XSD:

<xs:schema version="1.0" targetNamespace="http://www.knowledgemill.com/kmcs"
  xmlns:kmcs="http://www.knowledgemill.com/kmcs"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
  jaxb:version="2.0"
  xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
  jaxb:extensionBindingPrefixes="xjc"
  elementFormDefault="qualified">
    <xs:annotation>
        <xs:appinfo>
            <jaxb:globalBindings>
                <xjc:simple />
            </jaxb:globalBindings>
        </xs:appinfo>
    </xs:annotation>

    <xs:element name="Artifact" type="kmcs:Artifact"/>
    <xs:element name="EmailArtifact" type="kmcs:EmailArtifact"/>

    <xs:complexType name="Artifact">
        <xs:sequence>
            <xs:element name="artifactId" type="xs:string" minOccurs="0"/>
            <xs:element name="artifactType" type="xs:string" minOccurs="0"/>
            <xs:element name="contentHash" type="xs:string" minOccurs="0"/>
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="EmailArtifact">
        <xs:complexContent>
            <xs:extension base="kmcs:Artifact">
                <xs:sequence>
                    <xs:element name="subject" type="xs:string" minOccurs="0"/>
                    <xs:element name="threadSubject" type="xs:string" minOccurs="0"/>
                    <xs:element name="from" type="xs:string" minOccurs="0"/>
                    <xs:element name="to" type="xs:string" minOccurs="0"/>
                    <xs:element name="cc" type="xs:string" minOccurs="0"/>
                    <xs:element name="bcc" type="xs:string" minOccurs="0"/>
                    <xs:element name="messageId" type="xs:string" minOccurs="0"/>
                    <xs:element name="date" type="xs:date" minOccurs="0"/>
                    <xs:element name="size" type="xs:long" minOccurs="0"/>
                    <xs:element name="hasAttachment" type="xs:boolean" minOccurs="0"/>
                    <xs:element name="sensitivity" type="xs:string" minOccurs="0"/>
                    <xs:element name="headerHash" type="xs:string" minOccurs="0"/>
                </xs:sequence>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>


</xs:schema>

Как видно из приведенного выше фрагмента, EmailArtifact расширяет Artifact.

Код java-класса для EmailArtifact содержит следующее:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "EmailArtifact", propOrder = {
    "subject",
    "threadSubject",
    "from",
    "to",
    "cc",
    "bcc",
    "messageId",
    "date",
    "size",
    "hasAttachment",
    "sensitivity",
    "headerHash"
})
@XmlSeeAlso({
    ExtendedEmail.class
})
@XmlRootElement(name = "EmailArtifact")
public class EmailArtifact
    extends Artifact
{

    protected String subject;
    protected String threadSubject;
    protected String from;
    protected String to;
    protected String cc;
    protected String bcc;
    protected String messageId;
    @XmlSchemaType(name = "date")
    protected XMLGregorianCalendar date;
    protected Long size;
    protected Boolean hasAttachment;
    protected String sensitivity;
    protected String headerHash;

Код java-класса для Artifact содержит следующее:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Artifact", propOrder = {
    "artifactId",
    "artifactType",
    "contentHash"
})
@XmlSeeAlso({
    ManagedDocArtifact.class,
    EmailArtifact.class
})
public class Artifact {

    protected String artifactId;
    protected String artifactType;
    protected String contentHash;

В EmailArtifact мы видим, что он содержит @XmlRootElement, но базовый тип Artifact не содержит @XmlRootElement.

Как вы можете заставить XJC генерировать @XmlRootElement для всех классов, включая базовые типы.


person jallch    schedule 03.10.2009    source источник
comment
Для этого должен использоваться простой режим привязки. Вы уверены, что указываете его правильно?   -  person skaffman    schedule 05.10.2009
comment
Да, я вполне уверен - вот верхняя часть моего XSD с соответствующими globalBindings ... ‹? Xml version = 1.0 encoding = UTF-8?› ‹Xs: schema version = 1.0 xmlns: xs = w3.org/2001/XMLSchema xmlns: jaxb = java.sun.com/xml/ns/jaxb jaxb: version = 2.0 xmlns: xjc = java.sun.com/xml/ns/jaxb/xjc jaxb: extensionBindingPrefixes = xjc› ‹xs: annotation› ‹xs: appinfo› ‹Jaxb: globalBindings› ‹xjc: simple /› ‹/ jaxb: globalBindings› ‹/ xs: appinfo› ‹/ xs: annotation›   -  person jallch    schedule 05.10.2009
comment
Да, я думаю, это должно сработать, хотя я всегда использовал настройки внешней привязки, а не встроенные.   -  person skaffman    schedule 06.10.2009
comment
Спасибо за ответ. Также пробовал использовать внешний файл привязки. Опять ... не повезло. Обидно. Возможно, это часть стандарта, который мне не хватает, что базовые типы никогда не должны быть XmlRootElement. Хотя это кажется странной практикой ... Ну да ладно. На данный момент мне приходится прибегать к добавлению их вручную после генерации - неприятно :-( Вид поражает точку зрения, что XSD является источником истины.   -  person jallch    schedule 06.10.2009
comment
Попробуйте воспользоваться списком рассылки на jaxb.dev.java.net, вы можете получить более конкретный ответ.   -  person skaffman    schedule 07.10.2009


Ответы (2)


Просто привяжите с помощью xjb-файла:

<?xml version="1.0"?>
<jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jxb:extensionBindingPrefixes="xjc" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <jxb:bindings schemaLocation="path/to/myschema.xsd" node="/xs:schema">
    <jxb:globalBindings>
      <xjc:simple />
    </jxb:globalBindings>
  </jxb:bindings>
</jxb:bindings>

И не забудьте определить однотипный элемент:

<xs:complexType name="Artifact" />
<xs:element name="artifact" type="Artifact">
person Azee    schedule 30.03.2012
comment
Спасибо! Это лучшее решение. Это не требует изменения схемы xsd и не требует изменения сгенерированного корневого класса. - person Dmytro Boichenko; 08.11.2012
comment
Не могли бы вы объяснить вторую часть о необходимости определения и элемента одного и того же типа? Где это определяется? Я надеялся не менять XSD или сгенерированные классы. - person jacobq; 06.02.2015
comment
Это сработало и для меня. Оба свойства в jxb: привязки не нужны. Дополнительно мне пришлось предоставить компилятору xjc параметр командной строки extension = true (в Ant-Script). - person Heri; 11.11.2015
comment
Обратите внимание, что версии jaxb для java 9 (по крайней мере, jaxb2-maven-plugin:2.4) имеют ошибку, которая игнорирует такие утверждения в файлах xjb (на момент написания). См. github.com/highsource/maven-jaxb2-plugin/issues/120 - person slartidan; 21.02.2019

Этот вопрос ссылается на блог сообщение Кохсуке Кавагути, ранее работавшего над JAX-B или JAX-WS RI, в котором говорится о RI процесс принятия решения и отсутствие ясности по этому вопросу в спецификации.

В сообщении блога упоминается, что функция простого связывания является частью RI. Вы используете RI для генерации кода?

person DavidValeri    schedule 13.11.2009