JAXB использует имя элемента вместо типа при генерации pojo - PullRequest
0 голосов
/ 02 февраля 2019

С помощью jaxb я хочу создавать pojos из xsd.Но xsd предоставляется внешним поставщиком, где элементы имеют значимые имена, а типы странные.Просто пример:

<xs:element name="PersonAddress" type="PerAdr" />

<xs:complexType name="PerAdr">
    <xs:sequence>
        <xs:element name="street" type="xs:string" minOccurs="1" maxOccurs="unbounded" />
        <xs:element name="house" type="xs:string" minOccurs="1" maxOccurs="unbounded" />
    </xs:sequence>
</xs:complexType>

Так сгенерированный класс называется PerAdr.Как сделать так, чтобы он генерировал классы, в которых их имена являются именами элементов, а не типами, чтобы он генерировал в этом случае класс PersonAddress.

У меня огромный xsd, так что я думаю о способе сделать это умнее, а не просто написатьсотни строк в файле .xjb

1 Ответ

0 голосов
/ 04 февраля 2019

Я не совсем профессионал в JAXB.Но я посмотрел на спецификацию JAXB (здесь: http://download.oracle.com/otn-pub/jcp/jaxb-2.0-fr-oth-JSpec/jaxb-2_0-fr-spec.pdf) и обнаружил следующее:


Характеристики класса Element, полученного из схемы, получены на основе свойств«Компонента схемы объявления элемента» на странице 349 следующим образом:

  • Имя сгенерированного класса элемента Java получено изобъявление элемента {name} с использованием алгоритма преобразования идентификатора имени XML в имя Java для имен классов.

  • Каждый сгенерированный класс Element должен расширять Javaкласс значений javax.xml.bind.JAXBElement<T>. Следующий маркер указывает имя класса Java, полученное из схемы, которое будет использоваться для универсального параметра T.

  • Если объявление элемента {определение типа} is

    • Anonymous : для общего параметра T из второго маркера задан класс, производный от схемы, представленный как анонимныйопределение типа, сгенерированное как спецификацияd в Разделе 6.7.3.
    • Именовано: Общий параметр T из второго маркера установлен на класс Java, представляющий объявление элемента {определение типа} .

Итак, можно сделать вывод: получив элемент XSD с именованным типом XSD, вы получитеиметь дело с Java-классом, представляющим этот тип и названным в его честь.Это логичноВ конце концов, у вас могут быть разные элементы XSD с одинаковым глобальным типом.Это отображение по умолчанию.

Однако JAXB допускает настройки (схемы XML), с помощью которых вы можете переопределять определенные вещи.Например, вы можете изменить имя класса Java, сгенерированного типом XSD, например:

<xs:complexType name="USAddress">
  <xs:annotation> <xs:appinfo>
    <jaxb:class name="MyAddress" />
  </xs:appinfo></xs:annotation>
  <xs:sequence>...</xs:sequence>
  <xs:attribute name="country" type="xs:string"/>
</xs:complexType>

Таким образом, вместо USAddress, результирующий класс Java будет называться MyAddress.Это похоже на решение вашей проблемы, но чтобы воспользоваться этим преимуществом, вам нужно будет изменить каждое определение типа в вашем XSD, что звучит устрашающе, поскольку ваша схема огромна.

Итак, что вы можете сделать?

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

Любая автоматизация возможна только тогда, когда отношениеЭлемент XSD <-> его тип XSD уникален!В этом случае вы можете получить имя типа из имени элемента: сделать его таким же или добавить, например, префикс T: TPersonAddress.

Это обычно называется рефакторинг и может быть сделано автоматически.Вопрос в том, как?

Ну, поскольку XSD - это XML, вы можете написать XSLT-скрипт , который выполняет необходимое преобразование.Но это может быть не так просто, потому что вам придется немного разобрать схему.То есть распознать каждый элемент XSD и найти соответствующий тип XSD, а затем изменить имя типа в обоих местах.Кроме того, вы можете вставить эти директивы настройки (<jaxb:...> элементы) в определение каждого типа XSD, как упомянуто выше.Я не знаю, сколько потребуется, чтобы запрограммировать такие вещи.Это определенно сводится к созданию индекса (с конструкцией <xsl:key>) и итерации по нему.


В качестве альтернативы, я могу предложить вам неортодоксальный подход .Мы разработали инструмент под названием FlexDoc / XML .По сути, это преобразователь XML-файлов во что угодно.Преобразование программируется с использованием шаблонов , которые работают аналогично XSLT.

ThПервоначальная идея заключалась в том, чтобы распространить этот XSLT-подобный подход на любой тип источников данных на основе Java, предоставляемых через различные API.Например, у нас есть аналогичный продукт под названием FlexDoc / Javadoc , который имитирует стандарт Javadoc.Но затем мы поняли, что сам XML также является хорошим полем, полным различных тяжелых задач, для которых XSLT слишком легок.Например, создание легко ориентируемой единой документации сотнями файлов XSD и WSDL, для которых у нас теперь есть два набора шаблонов: XSDDoc и WSDLDoc .(Мы также работаем над аналогичной схемой JSON).

Используя FlexDoc / XML , можно создать шаблон, который делает то, что вам нужно (переименовывая эти типы XSD).Это может быть достигнуто в течение часа, и мы сделаем это за вас, если вы в конечном итоге приобретете лицензию «FlexDoc / XML SDK».(Люди обычно покупают лицензию SDK для настройки шаблонов XSDDoc / WSDLDoc . Но ее можно в равной степени использовать как отдельный инструмент для таких задач, как ваша.)

...