我目前正在使用JAXB生成java类以解组XML。现在我想创建一个与第一个非常相似的新模式,并使生成的类实现相同的接口。
比如说,我有两个模式文件,用于定义具有相似标签的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()
方法。
我已经查看了一些documentation的映射接口,但这似乎只适用于已经有要映射到DOM的java类的情况。
另外,我尝试使用此external plugin,但它似乎不起作用。这是我的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生成类?
更新
我尝试使用Interface Insertion插件但由于某种原因无法使其正常工作。这就是我调用xjc的方式,但就好像插件jar没有从类路径中获取一样:
$ 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
有什么想法吗?
答案 0 :(得分:43)
不幸的是,看起来某些其他答案中提到的界面注入插件不再受到良好支持。事实上,我无法找到下载的JAR。
值得庆幸的是,JAXB2 Basics Plugins提供了一种类似的机制,用于向生成的JAXB存根添加接口(请参阅Inheritance plugin)。
继承插件文档有一个示例,显示了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 Basics Plugins文档包含有关使用Ant和Maven插件的说明。您也可以直接从命令行使用它,但命令有点乱(由于您必须添加到类路径的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插件提供了许多其他有用的工具(例如equals,hashCode和toString方法的自动生成)。
答案 1 :(得分:8)
对于你的情况可能有些过分,但我使用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.Adult
和com.foo.generated.Adult
可能会因你的目的而过度杀伤,但它对我们有用。
答案 2 :(得分:3)
对我有用的答案是Jim Hurne使用JAXB2 Basics插件的例子。但他链接的文档似乎不再可用,以供参考,这就是我配置maven插件的方式:
<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>
答案 3 :(得分:3)
对于这种简单的情况,可以在不使用JAXB RI Vendor Extensions 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”,并生成类,而不是接口)时,它给了我所需的输出 - 我生成的所有类都实现了公共接口。
答案 4 :(得分:1)
在我的例子中,通过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-task时,错误仍然存在。给出的错误信息令人恼火,因为在我的情况下,真正的原因是在试图加载的类文件中的错误版本号(请参阅下面的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
答案 5 :(得分:0)
interface-insertion插件的文档建议使用以下内容
[ 要从命令行使用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
答案 6 :(得分:0)
如果将类型提取到导入到adult.xsd和kid.xsd的常用XSD中,该怎么办?或者您是否有需要它们实现的现有界面?
答案 7 :(得分:0)
对于那些希望帮助构建更复杂模式的JAXB数据绑定文件的人 - 最新的开源XML工具 - CAM Editor v2.2现在支持这一点。
您可以访问资源和下载网站以获取分步指南,并查看该工具页面顶部的下载部分。
http://www.cameditor.org/#JAXB_Bindings
享受。
答案 8 :(得分:-2)