2009-08-13 87 views
47

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

比方说,我有一个定义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我” d喜欢生成两个类文件:

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但它是因为如果该插件罐子是没有得到从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 

任何想法?

+0

Interface Insertion插件可用于使从XSD元素生成的类实现特定的接口。这里你想根据模式名称生成一个类 - 你需要另一个插件来完成。 我已经使用maven成功地完成了界面插入工作。让我知道你是否需要细节。 接口插入的来源在这里:https://jaxb2-commons.dev.java.net/interface-insertion/xjc-if-ins-src.jar – rochb 2009-11-13 16:43:45

+0

是要走的路。 – rochb 2009-11-21 14:44:50

回答

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基础插件文件包括使用与Ant和Maven插件的说明。你也可以用它直接在命令行,但命令是有点乱(由于罐的数量,您必须添加到classpath):

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基础插件提供了许多其他您可能也会发现有用的实用程序(例如equals的自动生成,hashCode和toString方法)。

+0

您的示例利用了'maven-jaxb2-plugin'的扩展或核心功能......是否有'cxf-xjc-plugin'类似的扩展名,它允许我们设置类似'-Xinheritance'的东西? – pulkitsinghal 2013-12-28 18:24:10

+1

发现'cxf-xjc-plugin'也可以利用类似的设置,如果它的调整是这样的:https://gist.github.com/pulkitsinghal/8163296 – pulkitsinghal 2013-12-28 19:44:14

+0

此外,给定示例的正确XPATH应该是 // xs:element [@ name ='Person']/xs:complexType [1] – RoyB 2014-12-30 13:57:08

0

所述用于接口插入插件文档建议的下列

[ 要从命令行使用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

  • 我会公布这是一个评论,但我没有足够的积分发表评论。
8

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

你会申报的线沿线的一个方面:这将接口com.foo.Person添加到类com.foo.generated.Adultcom.foo.generated.Adult

可能是矫枉过正,你的目的

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

    declare parents: 
     com.foo.generated.Kid 
    implements com.foo.Person; 
} 

,但它为我们工作。

+0

我想这只适用于编译时编织,否则marshallers抱怨额外的'ajc $实例'属性。 – OrangeDog 2016-09-22 16:36:09

0

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

+0

不幸的是,我无法修改XSD。我希望纯粹使用JAXB绑定或插件来完成此操作,以便不需要对XSD进行任何更改。 – 2009-08-26 10:52:26

1

在我的情况下通过java命令行调用的罐子工作:

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

但是执行XJC蚂蚁任务的错误仍然时。给出的错误信息令人恼火,因为在我的情况下,真正的原因是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 
0

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

您可以访问资源和下载网站以获得分步指南,并在页面顶部查看该工具的下载部分。

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

享受。

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

这工作完美。虽然,版本是相当古老,我couldn没有得到相同的解决方案来处理“最新”版本 – Sean 2016-06-28 16:15:19

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更快更简单!

我最初怀疑这会工作,如文档状态:

The customization allows you to specify the fully qualified name of the Java interface that is to be used as the root interface of all the generated interfaces. This customization has no effect unless you are specifically generating interfaces with the globalBindings generateValueClass="false" switch.

但是,当我尝试过了与类似于上面的一个一个的绑定(没有指定generateValueClass =“假”,并产生类,而不是接口),它给了我需要的输出 - 我所有生成的类都实现了通用接口。

+2

这不是人们问的(通常是大多数人想要的),正如你所说,这将使所有的类实现相同的接口大多数情况下,这是无用的 – 2013-12-17 17:34:03

+1

不,这正是OP想要的;两个模式生成两个类都实现相同的接口,它也恰好是我在现实世界项目中的一个要求,所以有些时候不是根本没有用处,它是JAXB的一个相当不完善的地方,我不认为用它的一个例子存在问题 – 2013-12-18 10:18:52

+1

如果JAXB生成两个以上的类,添加一个全局bi使用的结局部分将导致所有实现Person接口的类,这对于由两个以上的类组成的域来说并不合理,其中并非所有对象都是人。 – 2013-12-18 12:07:26