Как создать аннотацию XMLElementWrapper с помощью xjc и настраиваемой привязки

Я использую JAXB и xjc для компиляции моей XML-схемы в классы Java. Я не хочу вручную редактировать эти сгенерированные классы. У меня есть такая схема xml:

<xs:element name="root">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="items">
        <xs:complexType>
          <xs:sequence>
            <xs:element ref="item" />
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>
</xs:element>

xjc генерирует класс Items, который содержит только список объектов Item. Есть ли шанс опустить класс Items и иметь список объектов Item непосредственно в классе Root?

Я знаю, что это можно сделать с помощью аннотации @XMLElementWrapper, но я не знаю, как указать xjc создать такую.

Спасибо за любые предложения!

С уважением, Маркус


person DEAD10CC    schedule 15.03.2010    source источник


Ответы (2)


Bjarne Hansen разработал плагин для xjc, который смог позаботиться об этом. К сожалению, ссылка на оригинальную реализацию уже мертва. Однако на github есть проект Дмитрия Кацубо, основанный на исходном коде Бьярна с некоторыми дополнительными улучшениями.

https://github.com/dmak/jaxb-xew-plugin


(Просто для справки: исходная ссылка, теперь мертвая: http://www.conspicio.dk/blog/bjarne/jaxb-xmlelementwrapper-plugin)

person Thomas    schedule 15.03.2010
comment
Томас, спасибо. Эта ссылка является первым надлежащим содержанием, которое я видел по этой теме. - person mahonya; 19.03.2012
comment
Я пытался некоторое время использовать этот плагин, но безрезультатно. Не уверен, что это совместимо с xjc 2.2.4 (это то, что у меня есть на данный момент). Кроме того, у меня нет jaxb-xjc.jar (xjc является частью инструментов JDK7). Наконец, я хочу вызвать xjc из командной строки, и все очень молчат о том, как это сделать (Kohsuke Kawaguchi говорит, что вы также можете сделать это из командной строки, но это не очень красиво.) Почему мы не можем просто иметь аннотацию jaxb:, чтобы указать xjc пропустить уровень, т.е. просто создать @XmlElementWrapper? - person Pierre D; 22.03.2012
comment
Обратите внимание, что мой ответ был двухлетней давности — тогда я использовал плагин, и он работал нормально, но, возможно, к настоящему времени он устарел. - person Thomas; 23.03.2012
comment
Для тех, кто столкнулся с этим, как и я, исследуя эту проблему, вы можете найти этот плагин в основном репозитории Maven с идентификатором группы com.github.jaxb-xew-plugin и идентификатором артефакта jaxb-xew-plugin. Код хранится по адресу github.com/dmak/jaxb-xew-plugin. - person davidfmatheson; 25.09.2012
comment
@davidfmatheson Хотите создать правильный ответ, чтобы немного уточнить это решение? - person Thomas; 26.09.2012

Сначала давайте разобьем вашу схему, чтобы не было сгенерированных внутренних классов:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    elementFormDefault="qualified">
    <xs:element name="root" type="Root" />

    <xs:complexType name="Root">
        <xs:sequence>
            <xs:element name="items" type="Items" />
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="Items">
        <xs:sequence>
            <xs:element name="item" type="xs:string" maxOccurs="unbounded" />
        </xs:sequence>
    </xs:complexType>
</xs:schema>

Вы все равно получите дополнительные классы, просто не все в одном файле. Теперь вы хотите добавить в свою сборку раздел для использования jaxb-xew-plugin. Я использую Maven, поэтому для меня это выглядит так:

<plugin>
    <groupId>org.jvnet.jaxb2.maven2</groupId>
    <artifactId>maven-jaxb2-plugin</artifactId>
    <version>0.8.2</version>
    <executions>
        <execution>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <args>
                    <arg>-no-header</arg>
                    <arg>-Xxew</arg>
                    <arg>-Xxew:instantiate lazy</arg>
                    <arg>-Xxew:delete</arg>
                </args>
                <plugins>
                    <plugin>
                        <groupId>com.github.jaxb-xew-plugin</groupId>
                        <artifactId>jaxb-xew-plugin</artifactId>
                        <version>1.0</version>
                    </plugin>
                </plugins>
            </configuration>
        </execution>
    </executions>
</plugin>

Если вы начинаете использовать пространства имен, чтобы ваши сгенерированные классы имели имена пакетов, оставьте флаг -Xxew:delete, так как я недавно исправил ошибку, из-за которой удалялись объекты, которых не должно быть. В качестве альтернативы вы можете взять код с github и использовать его как 1.1-SNAPSHOT.

Когда я это делаю, я получаю сгенерированный код, который, я думаю, вы ищете:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Root", propOrder = {
    "items"
})
public class Root {

    @XmlElementWrapper(name = "items", required = true)
    @XmlElement(name = "item")
    protected List<String> items;

    public List<String> getItems() {
        if (items == null) {
            items = new ArrayList<String>();
        }
        return items;
    }

    public void setItems(List<String> items) {
        this.items = items;
    }

}
person davidfmatheson    schedule 26.09.2012