生成实现接口的 JAXB 类
我目前正在使用 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() 方法。
我查看了一些用于映射接口的文档,但这似乎只是适用于当您已经拥有要映射到 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 没有从类路径中获取:
$ 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
有什么想法吗?
I'm currently using JAXB to generate java classes in order to unmarshall XML. Now I would like to create a new schema very similar to the first and have the classes that are generated implement the same interface.
Say for example, I have two schema files which define XML with similar tags:
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>
Using JAXB and XJC I'd like to generate two class files:
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 { ... }
}
where the Person interface defines the getName()
and getAge()
methods.
I've looked at some of the documentation for mapping interfaces but this appears to only be for the situation when you already have java classes that you want to map to a DOM.
Also, I've tried to use this external plugin but it doesn't appear to work. Here is my xjb binding file:
<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>
but this gives the following error:
$ 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.
Is it possible to generate a class with JAXB that implements an interface?
Update
I've tried using the Interface Insertion plugin but for some reason can't get it to work. This is how I'm calling xjc yet it is as if the plugin jar is not getting picked up from the 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
I get the error:
unrecognized parameter -Xifins
Any ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
不幸的是,其他一些答案中提到的接口注入插件似乎不再得到很好的支持。事实上,我无法找到可供下载的 JAR。
值得庆幸的是,JAXB2 基础插件提供了类似的机制,用于将接口添加到生成的 JAXB 存根(请参阅继承插件)。
继承插件文档有一个示例,显示了 XML 架构文件的外观。但是,由于您无法修改架构,因此可以使用外部绑定文件:
JAXB2 Basics Plugins 文档包含有关将插件与 Ant 和 Maven 一起使用的说明。您也可以直接从命令行使用它,但该命令有点混乱(由于您必须添加到类路径中的 jar 数量):
JAXB2 Basics Plugins 提供了许多其他实用程序,您可能也会发现它们很有用(例如 equals、hashCode 和 toString 方法的自动生成)。
Unfortunately, it looks like the interface-injection plugin mentioned in some of the other answers is no longer well-supported. In fact, I'm having trouble finding the JAR for download.
Thankfully, the JAXB2 Basics Plugins provides a similar mechanism for adding an interface to the generated JAXB stubs (see the Inheritance plugin).
The Inheritance plugin documentation has an example showing what the XML schema file might look like. However, since you cannot modify the schema, you can use an external bindings file instead:
The JAXB2 Basics Plugins documentation includes instructions for using the plugin with Ant and Maven. You can also use it straight from the command line, but the command is a bit messy (due to the number of jars you have to add to the classpath):
The JAXB2 Basics Plugins provides a number of other utilities which you might also find useful (such as autogeneration of equals, hashCode, and toString methods).
对于您的情况来说,这可能有点过分了,但我已经使用 AspectJ 完成了此操作(我们已经在该项目上使用了方面,因此我们已经有了依赖关系和暴露)。
您可以按照以下方式声明一个方面:
这会将接口
com.foo.Person
添加到类com.foo. generated.Adult
和com .foo. generated.Kid
对于您的目的来说可能有点过分了,但它对我们有用。
It might be overkill for your situation, but I have done this using AspectJ (we were already using aspects on that project so we already had the dependency and the exposure).
You'd declare an aspect along the lines of:
Which will add the interface
com.foo.Person
to the classescom.foo.generated.Adult
andcom.foo.generated.Kid
Might be overkill for your purpose, but it worked for us.
对我有用的答案是 Jim Hurne 使用 JAXB2 Basics 插件的示例。但他链接的文档似乎不再可用,因此作为参考,这就是我配置 Maven 插件的方式:
The answer that worked for me was Jim Hurne's example of using the JAXB2 Basics plugin. But the documentation he linked appears to be no longer available so for reference, this is how I configured the maven plugin:
对于这个简单的情况,无需使用第三方插件,使用 JAXB RI 供应商扩展 xjc:superInterface 自定义。应该注意的是,这种方法将导致所有生成的类都实现该接口。
示例绑定文件:
然后您只需运行 xjc 指定绑定文件并设置 -extension 标志。比引入 JAXB2Basics 更快/更简单!
我最初怀疑这是否有效,如文档所述:
但是当我使用与上面类似的绑定进行尝试时(没有指定generateValueClass =“false”,并生成类,而不是接口),它给了我所需的输出 - 我生成的所有类都实现了通用接口。
It is possible to achieve this for this simple case without using a 3rd Party plugin using the JAXB RI Vendor Extensions xjc:superInterface customization. It should be noted this approach will cause all generated classes to implement the interface.
Example bindings file:
You then just need to run xjc specifying the binding file and setting the -extension flag. Much quicker/simpler than bringing in JAXB2Basics!
I was initially sceptical that this would work as the documentation states:
But when I tried it out with a bindings similar to the one above (without specifying generateValueClass="false", and generating classes, not interfaces), it gave me the output I required - all my generated classes implemented the common interface.
在我的例子中,通过 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 时,错误仍然存在。给出的错误消息令人恼火,因为在我的例子中,真正的原因是 ant 尝试加载的类文件中的版本号错误(请参见下面的堆栈跟踪)。仅当您将以下内容添加到 ANT_OPTS 时,才会出现此正确的错误消息:
-Dcom.sun.tools.xjc.Options.findServices=true
In my case the command-line call via java -jar works:
java -jar $somepath/jaxb-xjc.jar -classpath $somepath/xjc-if-ins.jar my.xsd -d $destdir -b $bindingconfig -p $desiredpackage -extension -Xifins
However when executing the xjc ant-task the error remains. The error message given is irritating as the real reason in my case is a bad version number in a class file ant tries to load (see stacktrace below). This correct error message only appears when you add the following to ANT_OPTS:
-Dcom.sun.tools.xjc.Options.findServices=true
接口插入插件的文档建议以下内容
[
要从命令行使用接口插入插件调用 xjc,您可以编写:
]
我猜测您正在调用错误类的 main 方法 - com.sun.tools.xjc.XJCFacade。您可能应该使用确切的语法重试。
这是另一个论坛上讨论类似问题的链接。
http://forums.java.net/jive/message.jspa?messageID= 220686
The documentation for the interface-insertion plugin suggests the the following
[
To call xjc with the Interface Insertion Plugin from the command line, you may write:
]
I am guessing that you are calling the main method of the wrong class - com.sun.tools.xjc.XJCFacade. You should probably retry with the exact syntax.
Here is a link on another forum which discusses a similar issue.
http://forums.java.net/jive/message.jspa?messageID=220686
某种描述的 XJC plygin 就是您问题的答案,这只是找到一个有效的问题。它们的最佳来源在这里:
https://jaxb2-commons.dev.java.net/< /a>
特别是这个:
https://jaxb2-commons.dev。 java.net/interface-insertion/
An XJC plygin of some description is the answer to your problem, it's just a matter of finding one that works. The best source for them is here:
https://jaxb2-commons.dev.java.net/
In particular, this one:
https://jaxb2-commons.dev.java.net/interface-insertion/