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

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

问题描述

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

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