I want to unmarshall a XML-File with mixed Content. I found a thread on stackoverflow which seemed appropriate (JAXB- @XmlMixed usage for reading @XmlValue and @XmlElement) where the user bdoughan defined 3 Use-Cases to deal with mixed content.
The third use case would keep the text between the tags in a single String variable and save the elements in a List. Which is what I wanted. Unfortunately I couldn't get it to work and the thread is quite old and maybe outdated.
I've tried the Usecase #3 with a List of Objects and a List of my Reference Class. Also I tried @XmlElement and @XmlValue Annotations.
I'm using the javax.xml.bind jaxb-api in version 2.3.1 and the org.glassfish.jaxb jaxb-runtime in version 2.3.1 in a Maven Projec with Java SE Version 12.0.2.
A Sample XML I tested with
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Date>
2018.06.27
<reference id="AnyId1">
</reference>
</Date>
My Class Representation
@XmlRootElement(name="Date")
public class TestPojo {
@XmlMixed
public String getTextContent() {
return textContent;
}
public void setTextContent(String textContent) {
this.textContent = textContent;
}
@XmlElementRef(name="reference", type = Reference.class)
public List<Object> getRef() {
return ref;
}
public void setRef(List<Object> ref) {
this.ref = ref;
}
String textContent;
List<Object> ref = new ArrayList<Object>();
}
I'd expect that the xml is unmarshalled into a POJO object and the right values are assigned. The Objects variables (textContent & ref) are null after unmarshalling.
You could try this:
Using a Reference class as below,
@XmlAccessorType(XmlAccessType.FIELD)
public class Reference {
@XmlAttribute
private String id;
}
And your Root class,
@XmlRootElement(name="Date")
public class TestPojo {
@XmlMixed
@XmlAnyElement
private List<Object> textContent;
@XmlElement
private Reference reference;
}
This will unmarshall giving you the reference element and everything else in a List.
For the example you have it will be 2 entries. The date value/text along with tab character (\t) and new line characters (\n), and another entry with new line character.
So you can use this list to process the contents and use what you want.
If there is a cleaner solution, I am interested. Cheers
Update to answer to comment:
In order to be more clear with the fix. What I did was using @XmlElement
instead of @XmlElementRef
for a single Reference instead of list (cos that's what I saw in the xml).
Also I added the @XmlAnyElement
annotation for the mixed content made it a list. This is what fixed it. So sticking with your class, it would look like below:
@XmlRootElement(name="Date")
public class TestPojo {
List<Object> textContent;
Reference ref;
@XmlMixed
@XmlAnyElement
public List<Object> getTextContent() {
return textContent;
}
public void setTextContent(List<Object> textContent) {
this.textContent = textContent;
}
@XmlElement(name="reference")
public Reference getRef() {
return ref;
}
public void setRef(Reference ref) {
this.ref = ref;
}
}
The @XmlAccessorType
saved me time from writing getters and setters. For an explanation of what this annotation does with an example (and in relation to @XmlElement
, check this:
What is the difference between using @XmlElement before field and before getter declaration?