JAXB将多个XML元素解组为单个类

我有以下XML结构,它跨多个XML元素建模单个概念。 这种格式不在我的掌控之中。

   1 x   2 y   1 Channel name   2 Another channel name    

我想在我可以控制的数据库中对此进行建模,并且可以使用包含idtypename字段的更简单的Channel表。 因此,我想在Wrapper类的单个List解组。

可以自动使用@Xml...注释吗? 我目前正在使用JAXB解组成单独的@XmlElement(name="Channel")@XmlElement(name="ChannelName")类列表,然后在Channel上对瞬态ChannelName/name进行后处理,但我认为必须有一种更简单的自动方式来映射这些元素。 或者它是XSLT的工作?

知道XML作为HTTP文件POST文件进入并且我正在使用Spring 3,Java和Hibernate可能会有所帮助。 我希望EclipseLink JAXB(MOXy)中的某些东西可能有帮助:)

@XmlElementWrapper将完成这项工作:

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

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


这是我到目前为止所拥有的。 我仍然试图消除对辅助对象的需求。 此示例需要EclipseLink JAXB(MOXy) 。

模型对象

您的模型对象是:

 package example; import java.util.ArrayList; import java.util.List; public class Wrapper { private List channels = new ArrayList(); public List getChannels() { return channels; } public void setChannels(List 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; } } 

帮手对象

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

 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 channelNames; @XmlTransient public Wrapper getWrapper() { for(ChannelName channelName : channelNames) { channelName.getChannel().setName(channelName.getName()); } return wrapper; } @XmlElementWrapper(name="Wrapper") @XmlElement(name="Channel") public List getChannels() { return wrapper.getChannels(); } public void setChannels(List channels) { wrapper.setChannels(channels); } @XmlElementWrapper(name="Wrapper") @XmlElement(name="ChannelName") public List getChannelNames() { return channelNames; } public void setChannelNames(List 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创建XML模式,将其另存为output.xsd文件: http : //www.xmlforasp.net/CodeBank/System_Xml_Schema/BuildSchema/BuildXMLSchema.aspx

使用JDK从项目根文件夹(。)运行下面的批处理脚本文件(将其命名为output.bat ),因为只有JDK具有xjc.exe工具(填写必要的详细信息):

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

哪里…

 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 

例:

假设项目文件夹的组织如下:

 . \_src 

从(。)命令提示符处运行以下命令:

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

它会创建一些文件:

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

然后,您可以在下面创建一些有用的方法来操作Output对象:

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