JAXB unmarshalling multiple XML elements into one class

I have the following XML structure that models a single concept for 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> 

I want to model this in a database in which I have control, and may have a simpler Channel table with id , type and name fields. Therefore, I would like to unmarshal one List<Channel> in the Wrapper class.

Can this be done using @Xml... annotations @Xml... automatically? I am currently using JAXB to @XmlElement(name="Channel") and @XmlElement(name="ChannelName") classes into separate lists, and then post-process the transient ChannelName/name to Channel , but I think I should Be a simpler automated way to map these items. Or is this work for XSLT?

This can help to find out that XML is included as the POST file of the HTTP file, and I use Spring 3, Java and Hibernate. I hope something in EclipseLink JAXB (MOXy) can help :)

+7
source share
2 answers

@XmlElementWrapper will do the job:

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

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


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

Model Objects

Your model objects:

 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 includes 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()); } } } 
+12
source

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

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

Run the batch script file (name it output.bat ) below from the project root folder (.) Using the JDK, since only the JDK has the xjc.exe tool (fill in the required data):

 "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 the project folder be organized as follows:

 . \_src 

Run the following command at a command prompt (.):

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

It will create several files:

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

You can then create some 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); } } 
+2
source

All Articles