从模式生成代码时删除中间类 [英] Remove intermediate class when generating code from schema

查看:31
本文介绍了从模式生成代码时删除中间类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们在 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
}

谢谢

推荐答案

UPDATE

人们编写了一些 XJC 插件来生成 @XmlElementWrapper 注释,而不是使用额外的包装类.

UPDATE

There are XJC plug-ins that people have written to generate the @XmlElementWrapper annotation instead of having the extra wrapper class.

或者,您可以自己使用 @XmlElementWrapper 创建类,并通过执行以下操作让生成的类引用它:

Alternative you could create the class with the @XmlElementWrapper yourself and have the generated classes reference it by doing the following:

文档

您可以手工制作自己的 Document 类以获得所需的行为.您可以通过利用 @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 架构 (schema.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 模式 (binding.xml) 生成 Java 模型时利用现有类

我们将使用一个外部绑定文件来表明在类生成期间我们希望将我们现有的类用于名为 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆