生成一个实现接口的JAXB类

我目前正在使用JAXB生成Java类,以解组XML。 现在我想创build一个与第一个类似的新模式,并且生成的类实现相同的接口。

举例来说,我有两个模式文件,它们用相似的标签来定义XML:

adult.xsd

<?xml version="1.0" encoding="UTF-8"?> <xs:element name="Person"> <xs:complexType> <xs:sequence> <xs:element name="Name" type="xs:string" /> <xs:element name="Age" type="xs:integer" /> <xs:element name="Job" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:element> 

kid.xsd

 <?xml version="1.0" encoding="UTF-8"?> <xs:element name="Person"> <xs:complexType> <xs:sequence> <xs:element name="Name" type="xs:string" /> <xs:element name="Age" type="xs:integer" /> <xs:element name="School" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:element> 

使用JAXB和XJC我想生成两个类文件:

 public class Adult implements Person { ... public String getName() { ... } public int getAge() { ... } public String getJob { ... } } public class Kid implements Person { ... public String getName() { ... } public int getAge() { ... } public String getSchool { ... } } 

Person接口定义了getName()getAge()方法。

我已经查看了映射接口的一些文档 ,但是这只是针对当您已经有想要映射到DOM的Java类的情况。

另外,我试图使用这个外部插件,但它似乎不工作。 这是我的xjb绑定文件:

 <jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:ext="http://xml.w-wins.com/xjc-plugins/interfaces" jxb:extensionBindingPrefixes="xjc"> <jxb:bindings schemaLocation="xsd/adult.xsd" node="xs:schema/xs:complexType[@name='Person']"> <ext:interface>mypackage.Hello</ext:interface> </jxb:bindings> </jxb:bindings> 

但是这给出了以下错误:

 $ java -cp "lib/activation.jar;lib/InterfacesXJCPlugin.jar;lib/jaxb1-impl.jar;lib/jaxb-api.jar;lib/jaxb-xjc.jar;lib/jsr173_1.0_api.jar" com.sun.tools.xjc.XJCFacade -p mypackage.myxml -extension -Xinterfaces xsd/adult.xsd -b binding.xjb parsing a schema... [ERROR] XPath evaluation of "xs:schema/xs:complexType[@name='Person']" results in empty target node line 8 of file:/C:/dev/jaxb/jaxb-ri/binding.xjb Failed to parse a schema. 

是否有可能用JAXB生成一个实现接口的类?

更新

我试过使用接口插入插件,但由于某种原因不能得到它的工作。 这就是我如何调用xjc,但是就像插件jar没有从classpath中拾取一样:

 $ java -cp "lib/xjc-if-ins.jar;lib/jaxb-xjc.jar" com.sun.tools.xjc.XJCFacade -p mypackage -extension -Xifins myschema.xsd -b binding.xjb 

我得到的错误:

 unrecognized parameter -Xifins 

有任何想法吗?

不幸的是,它看起来像其他答案中提到的接口注入插件不再得到很好的支持。 事实上,我无法find下载的JAR。

值得庆幸的是, JAXB2 Basics Plugins提供了一个类似的机制来将接口添加到生成的JAXB存根(请参阅inheritance插件 )。

inheritance插件文档有一个示例,显示XML模式文件的外观。 但是,由于您无法修改架构,因此可以使用外部绑定文件:

 <?xml version="1.0"?> <jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance" jxb:extensionBindingPrefixes="xjc"> <jxb:bindings schemaLocation="xsd/adult.xsd"> <jxb:bindings node="//xs:complexType[@name='Person']"> <inheritance:implements>mypackage.Hello</inheritance:implements> </jxb:bindings> </jxb:bindings> </jxb:bindings> 

JAXB2基础插件文档包含有关使用Ant和Maven插件的说明。 您也可以直接从命令行使用它,但命令有点麻烦(由于需要添加到类path中的jar的数量):

 java -jar jaxb-xjc.jar -classpath jaxb2-basics-0.5.3.jar,jaxb2-basics-runtime-0.5.3.jar, jaxb2-basics-tools-0.5.3.jar,commons-beanutils-0.5.3.jar, commons-lang.jar,commons-logging.jar -p mypackage.myxml -extension -Xinheritance xsd/adult.xsd -b binding.xjb 

JAXB2 Basics Plugins提供了许多其他的实用工具,您可能也会发现它们很有用(例如equals,hashCode和toString方法的自动生成)。

这可能是你的情况矫枉过正,但我​​已经做了这个使用AspectJ(我们已经在该项目上使用的方面,所以我们已经有了依赖和暴露)。

你会沿着以下方面宣布一个方面:

 public aspect MyAspect { declare parents: com.foo.generated.Adult implements com.foo.Person; declare parents: com.foo.generated.Kid implements com.foo.Person; } 

其中将接口com.foo.Person添加到类com.foo.generated.Adultcom.foo.generated.Adult

可能是为了你的目的矫枉过正,但它为我们工作。

对我而言,答案是Jim Hurne使用JAXB2 Basics插件的例子。 但他链接的文档似乎不再可用,以供参考,这是我如何configurationmaven插件:

  <plugin> <groupId>org.jvnet.jaxb2.maven2</groupId> <artifactId>maven-jaxb2-plugin</artifactId> <version>0.8.2</version> <executions> <execution> <goals> <goal>generate</goal> </goals> </execution> </executions> <configuration> <extension>true</extension> <args> <arg>-Xinheritance</arg> </args> <bindingDirectory>src/main/resources/xjb</bindingDirectory> <bindingIncludes> <include>**.xml</include> <!-- This Should reference the binding files you use to configure the inheritance --> </bindingIncludes> <schemaDirectory>src/main/resources/xsd</schemaDirectory> <generateDirectory>${project.build.directory}/generated-sources/jaxb</generateDirectory> <generatePackage>mypackage</generatePackage> <plugins> <plugin> <groupId>org.jvnet.jaxb2_commons</groupId> <artifactId>jaxb2-basics</artifactId> <version>0.5.3</version> </plugin> </plugins> </configuration> </plugin> 

对于这种简单的情况,可以使用JAXB RI供应商扩展 xjc:superInterface自定义,而不使用第三方插件。 应该指出,这种方法将导致所有生成的类实现接口。

示例绑定文件:

 <jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jxb:extensionBindingPrefixes="xjc"> <jxb:bindings schemaLocation="adult.xsd" node="/xs:schema"> <jxb:globalBindings> <xjc:superInterface name="com.example.model.Person"/> </jxb:globalBindings> </jxb:bindings> </jxb:bindings> 

然后你只需要运行xjc来指定绑定文件并设置-extension标志。 比引入JAXB2Basics更快更简单!

我最初怀疑这是否会像文档所述的那样工作:

通过定制,您可以指定要用作所有生成的接口的根接口的Java接口的完全限定名称。 除非您专门生成与globalBindings generateValueClass =“false”开关的接口,否则此自定义不起作用。

但是,当我用类似于上面的绑定(没有指定generateValueClass =“false”,并生成类,而不是接口)的绑定尝试了它,它给了我所需的输出 – 我所有生成的类实现了通用接口。

在我的情况下,通过java -jar的命令行调用工作:

java -jar $somepath/jaxb-xjc.jar -classpath $somepath/xjc-if-ins.jar my.xsd -d $destdir -b $bindingconfig -p $desiredpackage -extension -Xifins

但是,当执行xjc ant任务时,错误仍然存​​在。 给出的错误信息令人恼火,因为在我的情况下,真正的原因是ant类试图加载的类文件中的错误版本号(请参见下面的stacktrace)。 只有在将以下内容添加到ANT_OPTS时,才会显示此正确的错误消息: -Dcom.sun.tools.xjc.Options.findServices=true

 [xjc] java.lang.UnsupportedClassVersionError: Bad version number in .class file [xjc] at java.lang.ClassLoader.defineClass1(Native Method) [xjc] at java.lang.ClassLoader.defineClass(ClassLoader.java:620) [xjc] at org.apache.tools.ant.AntClassLoader.defineClassFromData(AntClassLoader.java:1134) [xjc] at org.apache.tools.ant.AntClassLoader.getClassFromStream(AntClassLoader.java:1320) [xjc] at org.apache.tools.ant.AntClassLoader.findClassInComponents(AntClassLoader.java:1376) [xjc] at org.apache.tools.ant.AntClassLoader.findClass(AntClassLoader.java:1336) [xjc] at org.apache.tools.ant.AntClassLoader.loadClass(AntClassLoader.java:1074) [xjc] at java.lang.ClassLoader.loadClass(ClassLoader.java:299) [xjc] at java.lang.ClassLoader.loadClass(ClassLoader.java:251) [xjc] at com.sun.tools.xjc.Options.findServices(Options.java:936) [xjc] at com.sun.tools.xjc.Options.getAllPlugins(Options.java:336) [xjc] at com.sun.tools.xjc.Options.parseArgument(Options.java:632) [xjc] at com.sun.tools.xjc.Options.parseArguments(Options.java:742) [xjc] at com.sun.tools.xjc.XJC2Task._doXJC(XJC2Task.java:444) [xjc] at com.sun.tools.xjc.XJC2Task.doXJC(XJC2Task.java:434) [xjc] at com.sun.tools.xjc.XJC2Task.execute(XJC2Task.java:369) [xjc] at com.sun.istack.tools.ProtectedTask.execute(ProtectedTask.java:55) [xjc] at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291) [xjc] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [xjc] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [xjc] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [xjc] at java.lang.reflect.Method.invoke(Method.java:585) [xjc] at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106) [xjc] at org.apache.tools.ant.Task.perform(Task.java:348) [xjc] at org.apache.tools.ant.Target.execute(Target.java:390) [xjc] at org.apache.tools.ant.Target.performTasks(Target.java:411) [xjc] at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1360) [xjc] at org.apache.tools.ant.Project.executeTarget(Project.java:1329) [xjc] at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41) [xjc] at org.apache.tools.ant.Project.executeTargets(Project.java:1212) [xjc] at org.apache.tools.ant.Main.runBuild(Main.java:801) [xjc] at org.apache.tools.ant.Main.startAnt(Main.java:218) [xjc] at org.apache.tools.ant.launch.Launcher.run(Launcher.java:280) [xjc] at org.apache.tools.ant.launch.Launcher.main(Launcher.java:109) [xjc] [xjc] failure in the XJC task. Use the Ant -verbose switch for more details 

一个XJC的plygin的一些描述是你的问题的答案,这只是find一个工作的问题。 他们的最佳来源是:

https://jaxb2-commons.dev.java.net/

特别是这一个:

https://jaxb2-commons.dev.java.net/interface-insertion/

接口插入插件的文档build议如下

[要从命令行使用Interface Insertion Plugin调用xjc,可以这样写:

 java -cp $JAXB_HOME/share/lib/xjc-if-ins.jar -extension -Xifins schema 

]

我猜你正在调用错误类的主要方法 – com.sun.tools.xjc.XJCFacade。 你可能应该重试确切的语法。

这是另一个讨论类似问题的论坛的链接。 http://forums.java.net/jive/message.jspa?messageID=220686

  • 我会张贴这个评论,但我没有足够的评论意见。

如果您将types提取到导入到adult.xsd和kid.xsd的常见XSD中,该怎么办? 还是你有一个现有的接口,你需要他们来实现?

对于那些希望为更复杂的模式构buildJAXB数据绑定文件的人员 – 最新的开源XML工具 – CAM Editor v2.2现在支持这一点。

您可以访问资源和下载站点的逐步指南,并在页面顶部看到下载部分的工具。

http://www.cameditor.org/#JAXB_Bindings

请享用。