从架构生成代码时删除中间类 [英] Remove intermediate class when generating code from schema
问题描述
假设我们在XSD中将集合类型定义为
Let's assume we defined a collection type in XSD as
<xs:complexType name="Foos">
<xs:sequence>
<xs:element name="foo" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:all>
<xs:element name="bar" type="xs:string"/>
<xs:element name="baz" type="xs:string"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
使用XJC从中生成Java代码时,类型粗略转换为
When generating Java code from it using XJC the type roughly translates to
public class Foos {
public List<Foos.Foo> getFoos();
public static class Foo {
public String getBar();
public String getBaz();
}
}
由于集合类型是其他类型的一部分,例如作为文档的根,生成的代码的客户端代码看起来有点像这样
As the collection type is part of some other type such as the root of the document, client code of the generated code looks somewhat like this
for(Foo foo : document.getFoos().getFoos())
{
//do something
}
如果不手动编写包装器,有没有办法让客户端代码变得不那么难看?
Is there any way to make the client code less ugly without writing a wrapper manually?
看起来应该是这样的
for(Foo foo : document.getFoos())
{
//do something
}
谢谢
推荐答案
更新
有人编写XJC插件来生成 @XmlElementWrapper
注释而不是额外的包装类。
UPDATE
There are XJC plug-ins that people have written to generate the @XmlElementWrapper
annotation instead of having the extra wrapper class.
- https://github.com/dmak/jaxb-xew-plugin
您可以自己使用 @XmlElementWrapper
创建类,并让生成的类引用它执行以下操作:
Alternative you could create the class with the @XmlElementWrapper
yourself and have the generated classes reference it by doing the following:
文档
您可以手工制作自己的文档
类以获得所需的行为。您可以通过利用 @XmlElementWrapper
注释获取分组元素来获得您正在寻找的行为。
You could handcraft your own Document
class to get the desired behaviour. You can get the behaviour you are looking for by leveraging the @XmlElementWrapper
annotation to get a grouping element.
package forum18247182;
import java.util.*;
import javax.xml.bind.annotation.*;
public class Document {
private List<Foos.Foo> foos = new ArrayList<Foos.Foo>();
@XmlElementWrapper
@XmlElement(name="foo")
public List<Foos.Foo> getFoos() {
return foos;
}
}
XML架构(架构) .xsd)
这是一个基于我将使用的片段的扩展XML模式。
Here is an expanded XML schema based on your fragment that I will use.
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/schema"
xmlns="http://www.example.org/schema"
elementFormDefault="qualified">
<xs:element name="document" type="Document"/>
<xs:complexType name="Document">
<xs:sequence>
<xs:element name="foos" type="Foos"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Foos">
<xs:sequence>
<xs:element name="foo" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:all>
<xs:element name="bar" type="xs:string" />
<xs:element name="baz" type="xs:string" />
</xs:all>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
从XML架构生成Java模型时利用现有类(binding.xml)
我们将使用外部绑定文件来指示在类生成期间我们希望将现有类用于名为 Document的复杂类型
。
We will use an external binding file to indicate that during class generation we wish to use our existing class for the complex type called Document
.
<jxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<jxb:bindings schemaLocation="schema.xsd">
<jxb:bindings node="//xs:complexType[@name='Document']">
<jxb:class ref="forum18247182.Document"/>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
XJC致电
我们将使用 -b
选项指定我们的绑定文件。我们还将使用 -p
选项强制生成的类的包名称与我们的 Document
类的包名称相匹配。我们还可以使我们的 Document
类的包名与从XML模式生成类所产生的包名匹配。
We will use the -b
option to specify our binding file. We will also use the -p
option to force the package name of the generated classes to match that of our Document
class. We could also have made the package name of our Document
class match the package name that results from generating classes from the XML schema.
xjc -b binding.xml -p forum18247182 schema.xsd
演示代码
package forum18247182;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
import forum18247182.Foos.Foo;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance("forum18247182");
Unmarshaller unmarshaller = jc.createUnmarshaller();
StreamSource xml = new StreamSource("src/forum18247182/input.xml");
Document document = unmarshaller.unmarshal(xml, Document.class).getValue();
for(Foo foo : document.getFoos())
{
System.out.println(foo);
}
}
}
输出
以下是运行演示代码的输出:
Below is the output from running the demo code:
forum18247182.Foos$Foo@51f3336e
forum18247182.Foos$Foo@35b5a4ca
这篇关于从架构生成代码时删除中间类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!