需要以下情况的帮助: 用户可以生成自己的数据结构,这些数据结构存储为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>
在出现新的或修改过的模式后,它会被Schema编译器自动解析,生成,编译并打包到用户jar中的java源代码:
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源代码。
答案 0 :(得分:8)
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>
有关详细信息,请参阅:
还可以通过外部绑定文件提供架构注释。有关示例,请参阅:
答案 1 :(得分:5)
非常感谢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 inteface轻松执行转换。
答案 2 :(得分:1)
我不相信使用JAXB本身有一种简单的方法。有许多不常见的自定义选项 - 有关详细信息,请阅读section 7 of JSR222。
如果您对输入模式有一些控制权,那么您可能需要考虑使用XSLT来转换模式。我相信这可以通过使用javax.xml.transform.dom.DOMResult
实例作为转换的目标并将输出用作DOM树(例如,在结果上调用getNode()
)作为{{1的输入来完成}}。一个基本的转变将是取代:
parseSchema
有类似的东西:
<xs:complexType name="foo">
<!-- CONTENTS -->
</xs:complexType>
当然这只适用于简单的情况。如果您已经在模式文件中具有继承,那么您将不得不在XSLT中进行一些过滤,该过滤仅将此变换应用于尚未扩展的类型。
答案 3 :(得分:0)
这是一个古老的话题,但仅作记录:
您可以使用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
在线上有更多示例。