Преобразование нескольких пространств имен XSD в Java

#java #xml #maven #xsd #jaxb

#java #xml #maven #xsd #jaxb

Вопрос:

Когда мне нужно было преобразовать XSD в java, я всегда использовал JAXB. Для автоматизации обновлений XSD на java project maven поставляется в справке jaxb2-maven-plugin . Стандартная конфигурация pom.xml для этого разговора выглядит следующим образом:

 <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>jaxb2-maven-plugin</artifactId>
    <configuration>
      <clearOutputDir>false</clearOutputDir>
      <extension>true</extension>
      <arguments>
        <argument>-Xfluent-api</argument>
      </arguments>
    </configuration>
    <executions>
      <execution>
        <id>generate-schema</id>
        <goals>
          <goal>xjc</goal>
        </goals>
        <configuration>
          <sources>
            <source>xsd/xsd_location</source>
          </sources>
          <sourceType>xmlschema</sourceType>
          <xjbSources>
            <xjbSource>xsd/LocalDateTimeBinding.xjb</xjbSource>
          </xjbSources>
          <packageName>com.example.schema</packageName>
        </configuration>
      </execution>
</plugin>
 

Куда xsd/xsd_location я помещаю свои файлы XSD и xsd/LocalDateTimeBinding.xjb содержит адаптер LocalDateTime для JAVA 8 , чтобы избежать joda.time. Исходные тексты были сгенерированы в target папку java под именем пакета com.example.schema . С простым XSD все работало отлично. На этот раз у меня сложный вопрос, так что я не знаю, что делать. Проблема связана с несколькими пространствами имен, содержащими одни и те же типы. Пример XSD выглядит следующим образом:

 <?xml version='1.0' encoding='UTF-8'?>
<xsd:schema xmlns="http://mydaomain.com/BusinessObjects/Common/AdditionalInformationDataListType/V2" targetNamespace="http://example.com/BusinessObjects/Common/AdditionalInformationDataListType/V2" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns0="http://example.com/BusinessObjects/Common/AdditionalInformationDataType/V1" xmlns:ns1="http://example.com/BusinessObjects/Common/AdditionalInformationDataType/V2">
  <xsd:import namespace="http://example.com/BusinessObjects/Common/AdditionalInformationDataType/V1" schemaLocation="../../../../BusinessObjects/Common/AdditionalInformationDataType/V1/AdditionalInformationDataType.xsd"/>
  <xsd:import namespace="http://example.com/BusinessObjects/Common/AdditionalInformationDataType/V2" schemaLocation="../../../../BusinessObjects/Common/AdditionalInformationDataType/V2/AdditionalInformationDataType.xsd"/>
  <xsd:complexType name="AdditionalInformationDataListType">
    <xsd:sequence>
      <xsd:choice minOccurs="0" maxOccurs="unbounded">
        <xsd:element name="additionalInformationDataV1" type="ns0:AdditionalInformationDataType" minOccurs="0" maxOccurs="unbounded"/>
        <xsd:element name="additionalInformationDataV2" type="ns1:AdditionalInformationDataType" minOccurs="0" maxOccurs="unbounded"/>
      </xsd:choice>
    </xsd:sequence>
  </xsd:complexType>
</xsd:schema>
 

Проблема в том, что

 ../../../../BusinessObjects/Common/AdditionalInformationDataType/V1/AdditionalInformationDataType.xsd
 

и

 ../../../../BusinessObjects/Common/AdditionalInformationDataType/V2/AdditionalInformationDataType.xsd
 

находятся в разных папках, разных версиях XSD-типов, в разных пространствах имен, но оба имеют одно и то же имя типа.

Моя текущая конфигурация пытается поместить их в один и тот же пакет, и я получаю сообщение об ошибке, какой файл уже существует. Я не могу изменить XSD (и не хочу этого делать, потому что он содержит более 100 файлов).

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

Комментарии:

1. Пожалуйста, не отвечайте на вопрос. Я откатил / отредактировал ваш вопрос и удалил ответ. Добавьте ответ только в раздел ответов.

Ответ №1:

Я полагаю, что вы можете точно настроить имена пакетов для каждого пространства имен.

Я бы попробовал две вещи:

  1. Либо удалите «packageName» из плагина, либо (лучше)
  2. Определите имя пакета для каждого пространства имен с помощью файла настройки Jaxb
     <jxb:bindings version="1.0"
                   xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
                   xmlns:xsd="http://www.w3.org/2001/XMLSchema">

        <!--
            Change since version 2.0 of the j-m-p:

            Note that the schemaLocation path must point to the XSD file
            relative to *this* file, rather than the basedir.
        -->
      <jxb:bindings schemaLocation="../xsd/address.xsd" node="//xsd:schema">
          <jxb:schemaBindings>
             <jxb:package name="com.example.myschema"/>
          </jxb:schemaBindings>
      </jxb:bindings>

    </jxb:bindings>
 

Пример взят из документации по плагинам (прокрутите вниз до раздела 6 с использованием файла привязки XML Java).

Комментарии:

1. Как-то я пропустил эту часть.. Похоже, это то, что мне нужно, но полная схема содержит 3616 файлов XSD, поэтому это займет некоторое время.. Подумываю сделать скрипт bash для генерации привязок, а затем передать их в addon. Позже я обновлю свой прогресс

Ответ №2:

Как предложил Бабис Рутис в ответе, я закончил тем, что использовал файл привязок jaxb. Моя схема содержит много файлов, поэтому я не хотел делать это вручную.. Для автоматизации процесса я написал сценарий sh:

 bfile=bindings.xjb
binding='t<jxb:bindings schemaLocation="%s" node="//xsd:schema">ntt<jxb:schemaBindings>nttt<jxb:package name="%s"/>ntt</jxb:schemaBindings>nt</jxb:bindings>n'
echo '<jxb:bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" version="2.1">' > ${bfile}
for fname in $(find . -name '*.xsd' -print)
do
    case $fname in
         *"/V1/"*) 
            printf "$binding" "$fname" "com.example.schema.v1" >> ${bfile}
            ;;
         *"/V2/"*) 
             printf "$binding" "$fname" "com.example.schema.v2" >> ${bfile}
             ;; 
        *) 
             printf "$binding" "$fname" "com.example.schema" >> ${bfile}
             ;;
     esac
done
echo "</jxb:bindings>" >> ${bfile}
 

Он генерирует каждую версию в разных пакетах на основе пути к каталогу, и если у XSD нет версии — она переходит в основной пакет. Чтобы заставить его работать, необходимо удалить packageName из pom.xml и добавить это в конфигурацию привязок.