У меня есть этот 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.
Вот что я пытался до сих пор:
maven-jaxb22-plugin
вместо 21. Без разницы.Судя по Интернету, люди сталкиваются с этой проблемой по крайней мере с 2006 года, и она может быть связана с некоторыми проблемами распознавателя Xerces. Я надеюсь, что это не какая-то ошибка, которая скрывалась в течение 6 лет, и никто не пытался ее исправить.Есть ли у кого-то еще предложения? Может кто сталкивался с такой же проблемой и нашел решение? Единственный обходной путь, который я могу придумать, — это использовать «svn:externals», чтобы перетащить общую схему в подпроект и просто заново сгенерировать там классы, но это грязно и будет работать только тогда, когда вы можете подключиться к нашему репозиторию svn.
Заранее большое спасибо за прочтение этого длинного поста. Имейте в виду, что я взял все вышеперечисленное из существующих проектов и заменил некоторые пространства имен и другие вещи для анонимности, поэтому возможны некоторые опечатки.