2009-08-13 159 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