如何强制架构编译的类将特定类扩展到架构之外

发布于 2024-10-09 18:25:42 字数 1855 浏览 0 评论 0原文

以下情况需要帮助: 用户可以生成自己的数据结构,这些数据结构存储为 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 源之前以某种方式转换模式文件。

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>

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

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 {
  //
}

and

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

是伱的 2024-10-16 18:25:42

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>

有关详细信息,请参阅:

模式注释也可以通过外部绑定文件提供。有关示例,请参阅:

XJC has an extension for this purpose

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

For more information see:

The schema annotations can also be supplied via an external bindings file. For an example see:

扭转时空 2024-10-16 18:25:42

非常感谢 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 接口轻松执行转换。

Many thanks to D.Shawley for pointing out the right section in JSR 222. Here is final solution which might be helpful and time saving for someone else.
Original schema must be transformed as follows:

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

Transformation can be easily performed via org.w3c.dom.Document inteface.

我偏爱纯白色 2024-10-16 18:25:42

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

如果您对输入模式有一定的控制,那么您可能需要考虑使用 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 中进行一些过滤,仅将此转换应用于尚未扩展的类型。

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.

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>

with something like:

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

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.

瑾夏年华 2024-10-16 18:25:42

这是一个有点老的话题,但只是为了记录:

您可以使用 jaxb2 继承插件来做到这一点。像这样:

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

参见这里的示例 http:// /vistaofjavahorizo​​n.blogspot.com/2014/07/how-to-have-prefer-java-class.html

网上有更多示例。

It is a bit an old topic, but just for the record:

You can do this with the jaxb2 inheritance plugin. Like this:

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

See for example here http://vistaofjavahorizon.blogspot.com/2014/07/how-to-have-particular-java-class.html

There are more examples online.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文