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

查看:62
本文介绍了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>

我想在我可以控制的数据库中对此进行建模,并且可以更简单频道表格, id 类型名称字段。因此,我想在 Wrapper 类中解组成一个 List< Channel>

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)类列表,然后在频道上对瞬态频道名称/名称进行后处理,但我在想那里必须是一种更容易自动化的方式来映射这些元素。或者它是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和休眠。我希望 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):

  • http://bdoughan.blogspot.com/2010/09/xpath-based-mapping-geocode-example.html

这是我到目前为止所拥有的。我仍然试图消除对辅助对象的需求。此示例需要 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天全站免登陆