как заставить скомпилированные классы схемы расширять определенный класс вне схемы - PullRequest
6 голосов
/ 29 декабря 2010

Нужна помощь в следующих ситуациях: Пользователи могут создавать свои собственные структуры данных, которые хранятся как готовые JAXB-источники XSD, как показано ниже:

<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="Group" type="Group"/>
  <xs:element name="Parameter" type="Parameter"/>

  <xs:complexType name="Group">
    <xs:sequence>
      <xs:element name="caption" type="xs:string" minOccurs="0"/>
      <xs:element name="parameters" type="Parameter" nillable="true" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="Parameter">
    <xs:sequence>
      <xs:element name="key" type="xs:string" minOccurs="0"/>
      <xs:element name="group" type="Group" minOccurs="0"/>
      <xs:element name="value" type="xs:string" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>

После появления новой или измененной схемы она автоматически анализируется компилятором схемы, генерируя java-источники, компилируя их и упаковывая в пользовательские файлы jar:

  SchemaCompiler sc = XJC.createSchemaCompiler();
  // Input source for schema
  InputSource is = new InputSource(new StringInputStream(objectPackage.getObjectSchema()));
  // Parse
  sc.parseSchema(is);
  S2JJAXBModel model = sc.bind();
  // Generate source
  JCodeModel jCodeModel = model.generateCode(null, null);
  jCodeModel.build(packageSourceDirectory);
  // Compile and package 
  // ......

И все было в порядке, пока не было решено, что все пользовательские классы должны расширять один определенный известный класс, скажем UserRootObject:

package user.abc;
public class Group extends com.mycompany.xml.UserRootObject {
  //
}

и

package user.abc;
public class Parameter extends com.mycompany.xml.UserRootObject {
  //
}

Все на лету, я не могу заставить пользователей изменять свои файлы схемы, но я могу преобразовать их до генерации кода. Похоже, у меня есть два варианта, чтобы представить это UserRootObject: каким-то образом через JCodeModel или каким-то образом преобразовать файлы схемы перед созданием исходных кодов Java.

Ответы [ 4 ]

8 голосов
/ 05 января 2011

XJC имеет расширение для этой цели

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
           xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
           jaxb:extensionBindingPrefixes="xjc"
           jaxb:version="2.0">

    <xs:annotation>
       <xs:appinfo>
          <jaxb:globalBindings>
           <xjc:superClass name="com.mycompany.xml.UserRootObject"/>
          </jaxb:globalBindings>
       </xs:appinfo>
    </xs:annotation>
.
.
.
</xs:schema>

Для получения дополнительной информации см .:

Аннотации схемы также могут быть предоставлены через внешний файл привязок. Для примера см .:

5 голосов
/ 30 декабря 2010

Большое спасибо D.Shawley за то, что он указал на правильный раздел в JSR 222. Вот окончательное решение, которое может быть полезным и сэкономить время для кого-то еще. Исходная схема должна быть преобразована следующим образом:

    <xs:schema version="1.0" 
               xmlns:xs="http://www.w3.org/2001/XMLSchema" 
               xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" 
               jaxb:version="2.0" >

      <xs:element name="Group" type="Group"/>
      <xs:element name="Parameter" type="Parameter"/>


      <xs:complexType name="Group">
        <xs:complexContent>
          <xs:extension base="UserRootObject">
            <xs:sequence>
            <!-- params -->
            </xs:sequence>
          </xs:extension>
        </xs:complexContent>
      </xs:complexType>

      <xs:complexType name="Parameter">
        <xs:complexContent>
          <xs:extension base="UserRootObject">
            <xs:sequence>
            <!-- params -->
            </xs:sequence>
          </xs:extension>
        </xs:complexContent>
      </xs:complexType>

      <xs:complexType name="UserRootObject">
        <xs:annotation>
          <xs:appinfo>
            <jaxb:class name="UserRootObject" implClass="com.mycompany.xml.UserRootObject"/>
          </xs:appinfo>
        </xs:annotation>
      </xs:complexType>
    </xs:schema>

Преобразование можно легко выполнить через интерфейс org.w3c.dom.Document.

1 голос
/ 29 декабря 2010

Я не верю, что есть простой способ сделать это, используя сам JAXB.Существует ряд доступных параметров настройки, которые обычно не известны - для подробностей прочитайте раздел 7 JSR222 .

Если у вас есть некоторый контроль над схемами ввода, то вы можете рассмотретьиспользуя XSLT для преобразования схемы.Я считаю, что это можно сделать, используя экземпляр javax.xml.transform.dom.DOMResult в качестве цели преобразования и используя вывод в качестве дерева DOM (например, вызов getNode() в результате) в качестве ввода parseSchema.Базовое преобразование должно было бы заменить:

<xs:complexType name="foo">
  <!-- CONTENTS -->
</xs:complexType>

на что-то вроде:

<xs:complexType name="foo">
  <xs:complexContent>
    <xs:extension base="UserRootObject">
      <!-- CONTENTS -->
    </xs:extension>
  </xs:complexContent>
</xs:complexType>

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

0 голосов
/ 21 сентября 2018

Это немного старая тема, но только для записи:

Вы можете сделать это с помощью плагина наследования jaxb2. Как это:

<xs:complexType name="...">
  <xs:annotation>
    <xs:appinfo>
      <inheritance:extends>
         com.mycompany.xml.UserRootObject
      </inheritance:extends>
    </xs:appinfo>
  </xs:annotation>
  <!-- ... -->
</xs:complexType>

Смотри, например, здесь http://vistaofjavahorizon.blogspot.com/2014/07/how-to-have-particular-java-class.html

В сети есть и другие примеры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...