从架构生成代码时删除中间类

时间:2013-08-15 06:06:23

标签: xml jaxb xsd xjc

假设我们在XSD中将集合类型定义为

<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代码时,类型大致转换为

public class Foos {
  public List<Foos.Foo> getFoos();

  public static class Foo {
    public String getBar();
    public String getBaz();
  }
}

由于集合类型是某些其他类型的一部分,例如文档的根,所生成代码的客户端代码看起来有点像这样

for(Foo foo : document.getFoos().getFoos())
{
  //do something
}

如果不手动编写包装器,有没有办法让客户端代码变得不那么难看?

看起来应该是这样的

for(Foo foo : document.getFoos())
{
  //do something
}

由于

1 个答案:

答案 0 :(得分:9)

更新

人们编写了XJC插件来生成@XmlElementWrapper注释,而不是拥有额外的包装类。


原始答案

替代方法您可以自己创建具有@XmlElementWrapper的类,并让生成的类通过执行以下操作引用它:

<强>文档

您可以手工制作自己的Document课程以获得所需的行为。您可以通过利用@XmlElementWrapper注释获取分组元素来获得您正在寻找的行为。

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架构(schema.xsd)

这是一个基于我将使用的片段的扩展XML模式。

<?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的复杂类型。

<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模式生成类的包名称相匹配。

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);
        }
    }

}

<强>输出

以下是运行演示代码的输出:

forum18247182.Foos$Foo@51f3336e
forum18247182.Foos$Foo@35b5a4ca
相关问题