JAXB 将多个 XML 元素解组为单个类 [英] JAXB unmarshalling multiple XML elements into single class

查看:27
本文介绍了JAXB 将多个 XML 元素解组为单个类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下 XML 结构,它对多个 XML 元素中的单个概念进行建模.这种格式不在我的控制范围内.

I have the following XML structure, which is modelling a single concept across multiple XML elements. This format is not in my control.

<Output>
  <Wrapper>
    <Channel>
      <id>1</id>
      <type>x</type>
    </Channel>
    <Channel>
      <id>2</id>
      <type>y</type>
    </Channel>
    <ChannelName>
      <id>1</id>
      <name>Channel name</name>
    </ChannelName>
    <ChannelName>
      <id>2</id>
      <name>Another channel name</name>
    </ChannelName>
  </Wrapper>
</Output>

我想在一个我可以控制的数据库中对此建模,并且可以有一个更简单的Channel表,带有idtypename 字段.因此,我想在 Wrapper 类上解组为单个 List.

I want to model this in a database that I do have control over and can have a more simple Channel table with id, type and name fields. Therefore I would like to unmarshal into a single List<Channel> on the Wrapper class.

这可以通过 @Xml... 注释自动完成吗?我目前使用 JAXB 解组为单独的 @XmlElement(name="Channel")@XmlElement(name="ChannelName") 类列表,然后对Channel 上的瞬态 ChannelName/name 但我认为必须有一种更简单的自动化方法来映射这些元素.还是 XSLT 的工作?

Can this be done with @Xml... annotations automatically? I am currently using JAXB to unmarshal into separate @XmlElement(name="Channel") and @XmlElement(name="ChannelName") class lists and then post-processing the transient ChannelName/name on the Channel but I am thinking there must be an easier automated way to map these elements. Or is it a job for XSLT?

知道 XML 是作为 HTTP 文件 POST 文件进入的,并且我使用的是 Spring 3、Java 和 Hibernate,这可能会有所帮助.我希望 EclipseLink JAXB (MOXy) 中的某些内容可能会有所帮助 :)

It might help to know that the XML is coming in as an HTTP file POST file and I'm using Spring 3, Java and Hibernate. I'm hoping something in EclipseLink JAXB (MOXy) might help :)

推荐答案

@XmlElementWrapper 将完成这项工作:

@XmlElementWrapper will do the job:

@XmlElementWrapper(name="Wrapper")
@XmlElement(name="Channel")
private List<Channel> channels;

对于更高级的情况,您可以在 EclipseLink JAXB (MOXy) 中使用 @XmlPath 扩展:

For more advanced cases you can use the @XmlPath extension in EclipseLink JAXB (MOXy):

这是我目前所拥有的.我仍在努力消除对辅助对象的需求.此示例需要 EclipseLink JAXB (MOXy).

Here is what I have so far. I'm still trying to eliminate the need for the helper objects. This example requires EclipseLink JAXB (MOXy).

模型对象

您的模型对象是:

package example;

import java.util.ArrayList;
import java.util.List;

public class Wrapper {

    private List<Channel> channels = new ArrayList<Channel>();

    public List<Channel> getChannels() {
        return channels;
    }

    public void setChannels(List<Channel> channels) {
        this.channels = channels;
    }

}

和:

package example;

import javax.xml.bind.annotation.XmlID;

public class Channel {

    private String id;
    private String type;
    private String name;

    @XmlID
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

辅助对象

我目前的解决方案涉及一些辅助对象:

My current solution involves some helper objects:

package example.adapted;

import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;

import example.Channel;
import example.Wrapper;

@XmlRootElement(name="Output")
@XmlType(propOrder={"channels", "channelNames"})
public class AdaptedWrapper {

    private Wrapper wrapper = new Wrapper();
    private List<ChannelName> channelNames;

    @XmlTransient
    public Wrapper getWrapper() {
        for(ChannelName channelName : channelNames) {
            channelName.getChannel().setName(channelName.getName());
        }
        return wrapper;
    }

    @XmlElementWrapper(name="Wrapper")
    @XmlElement(name="Channel")
    public List<Channel> getChannels() {
        return wrapper.getChannels();
    }

    public void setChannels(List<Channel> channels) {
        wrapper.setChannels(channels);
    }

    @XmlElementWrapper(name="Wrapper")
    @XmlElement(name="ChannelName")
    public List<ChannelName> getChannelNames() {
        return channelNames;
    }

    public void setChannelNames(List<ChannelName> channelNames) {
        this.channelNames = channelNames;
    }

}

和:

package example.adapted;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlIDREF;

import example.Channel;

public class ChannelName {

    private String name;
    private Channel channel;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @XmlIDREF
    @XmlElement(name="id")
    public Channel getChannel() {
        return channel;
    }

    public void setChannel(Channel channel) {
        this.channel = channel;
    }

}

演示代码

package example;

import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;

import example.adapted.AdaptedWrapper;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(AdaptedWrapper.class);

        File xml = new File("input.xml");
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        AdaptedWrapper adaptedWrapper = (AdaptedWrapper) unmarshaller.unmarshal(xml);
        Wrapper wrapper = adaptedWrapper.getWrapper();

        for(Channel channel : wrapper.getChannels()) {
            System.out.println(channel.getName());
        }
    }

}

这篇关于JAXB 将多个 XML 元素解组为单个类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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