Не удается разрешить определения типов из импортированной схемы в XJC.

У меня есть этот API, использующий JAXB для удобного использования объектных моделей, сгенерированных из XML-схем компилятором XJC (XML-to-Java) через именованные ссылки. Он абстрагирует создание контекстов JAXB и поиск методов ObjectFactory с помощью всех видов фоновой магии и отражений. Суть его в том, что вы всегда определяете одну общую схему, а затем любое количество (может также быть 0) схем, «расширяющих» эту общую, каждая из которых приводит к своей собственной модели данных. Общая схема содержит многократно используемые определения, те, что расширяют ее, используют их для составления своих собственных моделей.

Теперь я столкнулся с ситуацией, когда я хотел бы повторно использовать общую схему для более чем одного проекта. Общие определения типов должны оставаться одинаковыми во всех проектах, и некоторый код будет создаваться на основе абстрактных классов, созданных на их основе. Поэтому мне нужно сначала сгенерировать классы для некоторой общей схемы, а затем сгенерировать их, расширяющие и использующие их отдельно. Я использую Maven для процесса сборки.

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

Предположим, моя общая схема называется «общая».xsd" и выглядит следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.foobar.com/general"
xmlns:gen="http://www.foobar.com/general"
elementFormDefault="qualified" attributeFormDefault="qualified">

    <!-- Element (will usually be root) -->
    <xs:element name="transmission" type="gen:Transmission" />

    <!-- Definition -->
    <xs:complexType name="Transmission" abstract="true">
        <xs:sequence>
            <!-- Generic parts of a transmission would be in here... -->
        </xs:sequence>
    </xs:complexType>

</xs:schema>

Рядом с ним есть файл привязок, чтобы сделать некоторую настройку именования и установить имя пакета для вывода:

<?xml version="1.0" encoding="UTF-8"?>
<bindings xmlns="http://java.sun.com/xml/ns/jaxb" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
    version="2.1">

    <!-- Bindings for the general schema -->
    <bindings schemaLocation="general.xsd" node="/xs:schema">

        <schemaBindings>
            <package name="com.foobar.models.general"/>
        </schemaBindings>

        <bindings node="//xs:complexType[@name='Transmission']">
            <!-- Some customization of property names here... -->
        </bindings>

</bindings>

Затем я должен был бы сгенерировать следующий бит в POM этого проекта. классы Java:

<plugin>
    <groupId>org.jvnet.jaxb2.maven2</groupId>
    <artifactId>maven-jaxb21-plugin</artifactId>
    <version>0.8.0</version>
    <executions>
        <execution>
            <id>xjc-generate</id>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <schemaDirectory>${basedir}/src/main/resources/com/foobar/schemas</schemaDirectory>
                <schemaLanguage>XMLSCHEMA</schemaLanguage>
                <addCompileSourceRoot>true</addCompileSourceRoot>
                <episode>true</episode>
                <removeOldOutput>true</removeOldOutput>
            </configuration>
        </execution>
    </executions>
</plugin>

Как видите, я использую подключаемый модуль JAXB2.1 Maven. Я установил параметр для создания файла эпизода для пошаговой компиляции. обходной путь; все, что он делает, это убеждается, что сначала все очищено, поэтому перекомпиляция принудительна.

Пока все хорошо. Этот проект компилируется без заминок. Следует отметить, что помимо сгенерированных классов Java, я также упаковываю схемы в полученный файл jar. Так что они доступны в classpath! Файл sun-jaxb.episodeнаходится в META-INF, как и должно быть.

Затем я начинаю проект, который использует схемы, которые будут расширять вышеуказанное, предварительно импортировав его Один из «подтипов» может выглядеть так (я назову его sub.xsd):

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.foobar.com/sub"
xmlns:sub="http://www.foobar.com/sub"
xmlns:gen="http://www.foobar.com/general"
elementFormDefault="qualified" attributeFormDefault="qualified">

    <xs:import namespace="http://www.foobar.com/general" />

    <!-- Definition -->
    <xs:complexType name="SubTransmission">
        <xs:complexContent>
            <xs:extension base="gen:Transmission">
                <xs:sequence>
                    <!-- Additional elements placed here... -->
                </xs:sequence>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>

</xs:schema>

Опять же, t вот файл привязок:

<?xml version="1.0" encoding="UTF-8"?>
<bindings xmlns="http://java.sun.com/xml/ns/jaxb" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
    version="2.1">

    <!-- Bindings for sub type -->
    <bindings schemaLocation="sub.xsd" node="/xs:schema">

        <schemaBindings>
            <package name="com.foobar.models.sub"/>
        </schemaBindings>

    </bindings>

</bindings>

А вот фрагмент из POM этого проекта, который заботится о генерации XJC:

<plugin>
    <groupId>org.jvnet.jaxb2.maven2</groupId>
    <artifactId>maven-jaxb21-plugin</artifactId>
    <version>0.8.0</version>
    <executions>
        <execution>
            <id>xjc-generate</id>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <schemaDirectory>${basedir}/src/main/resources/com/foobar/schemas</schemaDirectory>
                <schemaLanguage>XMLSCHEMA</schemaLanguage>
                <addCompileSourceRoot>true</addCompileSourceRoot>
                <episode>false</episode>
                <catalog>${basedir}/src/main/resources/com/foobar/schemas/catalog.cat</catalog>
                <episodes>
                    <episode>
                        <groupId>com.foobar</groupId>
                        <artifactId>foobar-general-models</artifactId>
                        <version>1.0.0-SNAPSHOT</version>
                        <scope>compile</scope>
                    </episode>
                </episodes>
                <removeOldOutput>true</removeOldOutput>
            </configuration>
        </execution>
    </executions>
</plugin>

Первоначально все схемы находились в одной папке, и у меня было расположение схемыатрибут в импорте установлен на general.xsd, который работал нормально. Но теперь, когда вещи разделены по проектам, я сталкиваюсь с проблемами. Первая проблема заключалась в том, что не удалось найти другую схему.Я решил эту проблему, взяв атрибут schemaLocationиз элемента , сохранив только атрибут namespaceи добавив файл каталога ( catalog.cat), ссылки на которые вы можете увидеть в приведенном выше отрывке POM. Его содержимое:

PUBLIC "http://www.foobar.com/general" "classpath:/com/foobar/schemas/general.xsd"

Кажется, это работает, так как я больше не получаю сообщение об ошибке, указывающее, что схема не может быть найдена. Но по какой-то причине разрешение фактических определений типов из импортированной схемы по-прежнему не удается. Вот исключение:

Error while parsing schema(s).Location [ file:/C:/NetBeans_groups/Test/SubModelBundle/src/main/resources/com/foobar/schemas/sub.xsd{...,...}].
org.xml.sax.SAXParseException: src-resolve: Cannot resolve the name 'gen:Transmission' to a(n) 'type definition' component.

Вот что я пытался до сих пор:

  • Использовать файл каталога. Частично успешно, так как теперь можно найти импортированную схему.
  • При компиляции общей схемы сгенерируйте файл эпизода и используйте его для компиляции подсхемы. Похоже, это не имеет значения, хотя это должно сыграть роль только после того, как тип будет разрешен, поэтому я не думаю, что это важно.
  • Используйте другую реализацию JAXP (примечание: неJAXB, JAXP). Он использовал другой, потому что я мог видеть это в трассировке стека исключения, но конечный результат тот же.
  • Используйте maven-jaxb22-pluginвместо 21. Без разницы.

Судя по Интернету, люди сталкиваются с этой проблемой по крайней мере с 2006 года, и она может быть связана с некоторыми проблемами распознавателя Xerces. Я надеюсь, что это не какая-то ошибка, которая скрывалась в течение 6 лет, и никто не пытался ее исправить.Есть ли у кого-то еще предложения? Может кто сталкивался с такой же проблемой и нашел решение? Единственный обходной путь, который я могу придумать, — это использовать «svn:externals», чтобы перетащить общую схему в подпроект и просто заново сгенерировать там классы, но это грязно и будет работать только тогда, когда вы можете подключиться к нашему репозиторию svn.

Заранее большое спасибо за прочтение этого длинного поста. Имейте в виду, что я взял все вышеперечисленное из существующих проектов и заменил некоторые пространства имен и другие вещи для анонимности, поэтому возможны некоторые опечатки.

15
задан Jean-Rémy Revy 20 July 2012 в 15:48
поделиться