如何强制架构编译的类将特定类扩展到架构之外 [英] how to force schema compiled classes to extend specific class outside schema

查看:33
本文介绍了如何强制架构编译的类将特定类扩展到架构之外的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在以下情况下需要帮助:用户可以生成自己的数据结构,这些数据结构存储为 JAXB-ready XSD 源,如下所示:

Need help with following situation: Users can generate their own data structures which are stored as JAXB-ready XSD sources like below:

<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>

出现新的或修改后的模式后,模式编译器会自动对其进行解析,生成、编译并打包到用户 jar 中的 java 源代码:

After new or modified schema appears it is automatically parsed by Schema compiler, java sources being generated, compiled and packaged into user jars:

  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:

And everything was ok until it was decided that all user-generated classes must extend one specific known class, say 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 源代码之前以某种方式转换模式文件.

Everything is on the fly, I can not force users to modify their schema files but I can transform them prior to code generation. Looks like I have two options to introduce that UserRootObject: somehow via JCodeModel or somehow transforming schema files before building Java sources.

推荐答案

我不相信使用 JAXB 本身有一种简单的方法可以做到这一点.有许多不为人知的自定义选项 - 请阅读 第 7 节 JSR222 了解详情.

I do not believe that there is an easy way to do this using JAXB itself. There are a number of customization options available that are not commonly known - read section 7 of JSR222 for details.

如果您对输入模式有一定的控制权,那么您可能需要考虑使用 XSLT 来转换模式.我相信这可以通过使用 javax.xml.transform.dom.DOMResult 实例作为转换的目标并将输出用作 DOM 树(例如,调用 getNode() 上)作为 parseSchema 的输入.一个基本的转换是替换:

If you have some control over the input schemas, then you might want to consider using XSLT to transform the schema. I believe that this can be done by using a javax.xml.transform.dom.DOMResult instance as the target of the transformation and using the output as a DOM tree (e.g., calling getNode() on the result) as the input to parseSchema. A basic transformation would be to replace:

<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 中进行一些过滤,只将此转换应用于尚未扩展的类型.

Of course this only works for the simple cases. If you already have inheritance in your schema files, then you will have to do some filtering in the XSLT that only applies this transform to types that do not already extend.

这篇关于如何强制架构编译的类将特定类扩展到架构之外的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆