JAXB unmarshalling multiple XML elements into single class

后端 未结 2 1187
北恋
北恋 2020-12-09 22:55

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


  <         


        
相关标签:
2条回答
  • 2020-12-09 23:13

    @XmlElementWrapper will do the job:

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

    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

    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).

    Model Objects

    Your model objects are:

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

    and:

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

    Helper Objects

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

    and:

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

    Demo Code

    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());
            }
        }
    
    }
    
    0 讨论(0)
  • 2020-12-09 23:19

    You can save your coding time by automating this process in JAXB:

    Create a XML schema for your XML using the link below as save it as output.xsd file: http://www.xmlforasp.net/CodeBank/System_Xml_Schema/BuildSchema/BuildXMLSchema.aspx

    Run the batch script file (name it as output.bat) below from the project root folder (.) using JDK as only JDK has xjc.exe tool (fill in the necessary details):

    "C:\Program Files\Java\jdk1.6.0_24\bin\xjc.exe" -p %1 %2 -d %3
    

    where...

    syntax: output.bat %1 %2 %3
    %1 = target package name
    %2 = full file path name of the generated XML schema .xsd 
    %3 = root source folder to store generated JAXB java files
    

    Example:

    let say project folder is organized as follows:

    .
    \_src
    

    Run following at command prompt from (.):

    output.bat com.project.xml .\output.xsd .\src
    

    It will create a few files:

    .
    \_src
      \_com
        \_project
          \_xml
            |_ObjectFactory.java
            |_Output.java
    

    Then, you can create a few useful methods below to manipulate Output objects:

    private JAXBContext jaxbContext = null;
    private Unmarshaller unmarshaller = null;
    private Marshaller marshaller = null;
    
    public OutputManager(String packageName) {
        try {
            jaxbContext = JAXBContext.newInstance(packageName);
            unmarshaller = jaxbContext.createUnmarshaller();
            marshaller = jaxbContext.createMarshaller();
        } catch (JAXBException e) {
        }
    }
    
    public Output loadXML(InputStream istrm) {
    
        Output load = null;
    
        try {
            Object o = unmarshaller.unmarshal(istrm); 
    
            if (o != null) {
    
                load = (Output) o;
    
            }
    
        } catch (JAXBException e) {
    
            JOptionPane.showMessageDialog(null, e.getLocalizedMessage(), e.getClass().getSimpleName(), JOptionPane.ERROR_MESSAGE);
    
        }
        return load;
    }
    
    public void saveXML(Object o, java.io.File file) {
    
        Output save = null;
    
        try {
            save = (Output) o;
    
            if (save != null) {
                marshaller.marshal(save, file);
            }
    
        } catch (JAXBException e) {
    
            JOptionPane.showMessageDialog(null, e.getLocalizedMessage(), e.getClass().getSimpleName(), JOptionPane.ERROR_MESSAGE);
    
        }
    }
    
    public void saveXML(Object o, FileOutputStream ostrm) {
    
        Output save = null;
    
        try {
    
            save = (Output) o;
    
            if (save != null) {
                marshaller.marshal(save, ostrm);
            }
    
        } catch (JAXBException e) {
    
            JOptionPane.showMessageDialog(null, e.getLocalizedMessage(), e.getClass().getSimpleName(), JOptionPane.ERROR_MESSAGE);
    
        }
    }
    
    0 讨论(0)
提交回复
热议问题