Reputation: 43823
I'm having a small problem with JAXB unmarshalling in that my input XML can be wrapped by one of two elements, for example:
<Output>
<Update>
<Channel>
<id>1</id>
</Channel>
<Channel>
<id>2</id>
</Channel>
</Update>
</Output>
or
<Output>
<Erase>
<Channel>
<id>1</id>
</Channel>
</Erase>
</Output>
My root class is unmarshalling the Channels to a HashMap using an @XmlJavaTypeAdapter and the code below works as expected.
@XmlRootElement(name="Output")
public class Output{
@XmlElement(name="Update")
@XmlJavaTypeAdapter(ChannelAdapter.class)
private HashMap<Long, Channel> allChannels;
public Map getChannels() {
return allChannels;
}
}
where Channels class is:
public class Channels {
@XmlElement(name="Channel")
public Channel[] channels;
}
and the Channel is:
@XmlAccessorType(XmlAccessType.FIELD)
public class Channel {
@XmlPath("id/text()")
private Long id;
}
and finally the ChannelAdapter is:
public class ChannelAdapter extends XmlAdapter<Channels, Map<Long, Channel>> {
@Override
public Map<Long, Channel> unmarshal(Channels value) { ... }
@Override
public Channels marshal(Map<Long, Channel> map) { ... }
}
However I thought I could just replace @XmlElement(name="Update")
with
@XmlElements({
@XmlElement(name="Update"),
@XmlElement(name="Erase")
})
but that results in an empty map.
Hard-coding to either @XmlElement(name="Update")
or @XmlElement(name="Erase")
works with one or other the input XML documents but I need something that will work with either of the wrapper elements. I tried using a @XmlElementWrapper
but that can only be used on a collection or array property which will not work since allChannels is a HashMap.
Could I please get an explain of what am I misunderstanding about the @XmlElements
annotation and also a way to get this working? Thanks!
Upvotes: 3
Views: 1251
Reputation: 11
Try to change your XSDs to something that let's Output incorporate a choice allowing the XML to use either of the elements but never ever both at the same time.
I don't know, however, how to annotate this via XmlElements. Try to build an XSD first an then generate the classes for looking up the annotations ;).
Upvotes: 1
Reputation: 7234
As far as I know, JAXB forces you to have a bidirectional data model; you cannot merge two children of a node into one without breaking this convention. So, you need to have two lists, one for Updates and one for Erases.
Because I've never used @XmlElements annotation, take my comment with care.
Upvotes: 1