JAXB- @XmlMixed usage for reading @XmlValue and @XmlElement
jaxb
Solution
I'll try to answer your question with an example:
input.xml
We will use the following XML document for this example. The `root` element has mixed content. Having mixed conent means that text nodes can appear mixed in with the elements. Since more than one text node can appear a unary property isn't a good fit.
<?xml version="1.0" encoding="UTF-8"?>
<root>
<root/>
Hello
<root/>
World
<root/>
</root>
Demo
The following code will be used in to read in the XML to object form and then write it back to XML.
package forum10940267;
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum10940267/input.xml");
Root root = (Root) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
USE CASE #1 - One List to Hold Mixed Content
`@XmlMixed` is most often used to with another annotation, so that the resulting `List` contains both element and text content. One advantage of this is that order is maintained so that the document can be round tripped.
package forum10940267;
import java.util.*;
import javax.xml.bind.annotation.*;
@XmlRootElement
public class Root {
private List<Object> mixedContent = new ArrayList<Object>();
@XmlElementRef(name="root", type=Root.class)
@XmlMixed
public List<Object> getMixedContent() {
return mixedContent;
}
public void setMixedContent(List<Object> mixedContent) {
this.mixedContent = mixedContent;
}
}
Output
The output matches the input.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<root/>
Hello
<root/>
World
<root/>
</root>
USE CASE #2 - Separate List for Mixed Content
You can can also introduce a separate list property for the text content.
package forum10940267;
import java.util.*;
import javax.xml.bind.annotation.*;
@XmlRootElement
public class Root {
private List<Object> mixedContent = new ArrayList<Object>();
private List<String> text;
@XmlElementRef(name="root", type=Root.class)
public List<Object> getMixedContent() {
return mixedContent;
}
public void setMixedContent(List<Object> mixedContent) {
this.mixedContent = mixedContent;
}
@XmlMixed
public List<String> getText() {
return text;
}
public void setText(List<String> text) {
this.text = text;
}
}
Output
The output no longer matches the input.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<root/>
<root/>
<root/>
Hello
World
</root>
USE CASE #3 - String Property for Text Content
Since text nodes can occur multiple times in mixed content, a non-List property isn't a good fit and it appears as though the `@XmlMixed` annotation is being ignored.
package forum10940267;
import java.util.*;
import javax.xml.bind.annotation.*;
@XmlRootElement
public class Root {
private List<Object> mixedContent = new ArrayList<Object>();
private String text;
@XmlElementRef(name="root", type=Root.class)
public List<Object> getMixedContent() {
return mixedContent;
}
public void setMixedContent(List<Object> mixedContent) {
this.mixedContent = mixedContent;
}
@XmlMixed
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
Output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<root/>
<root/>
<root/>
</root>
Problem
I saw a similar question being posted here, yet it did not help me solve the problem so I am posting my question here to see if someone can modify my code to make it work. Question: How to access mixed content String value and save it in setPhrase(String value) method? caption.xml: ``` <?xml version="1.0" encoding="UTF-8"?> <tt xmlns="link1" xmlns:prefix2="link2" prefix1:att1="att1"> <head> <styling> <style prefix1:att1="att1" prefix2:att2="att2" prefix2:att3="att3" prefix2:att4="att4" /> </styling> <layout /> </head> <body xmlns:prefix3="link3"> <div prefix1:att1="att1" prefix1:att2="att2"> <prefix3:info att1="att1" att2="att2" /> <p att1="att1" att2="att2" att3="att3"> <prefix3:status att1="att1" att2="att2" /> Hello World. </p> </div> </body> </tt> ``` Caption.java: ``` package com; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementRef; import javax.xml.bind.annotation.XmlElementRefs; import javax.xml.bind.annotation.XmlMixed; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; @XmlRootElement(name = "p") @XmlType(propOrder = { "att1", "att2", "att3", "phrase", "subelement"}) public class Caption { private String att1; private String att2; private String att3; private String phrase; private Subelement subelement = new Subelement(); @XmlMixed public void setPhrase(String value) { this.phrase = value; } public String getPhrase() { return phrase; } @XmlElementRefs({@XmlElementRef(name = "subelement", type = Subelement.class)}) @XmlMixed public void setSubelement(Subelement subelement ) { this.subelement = subelement; } public Subelement getSubelement() { return subelement; } @XmlAttribute public void setAtt1( String att1 ) { this.att1 = att1; } public String getAtt1() { return att1; } @XmlAttribute public void setAtt2( String att2 ) { this.att2 = att2; } public String getAtt2() { return att2; } @XmlAttribute public void setAtt3( String att3 ) { this.att3 = att3; } public String getAtt3() { return att3; } } ``` After using JAXB unmarshall and marshall I am able to get everything converted into and object and saved accorderling, except for the actual phrase "Hello World.". I know I must use some sort of @XmlMixed for this complex element but I cannot figure it out. My current output.xml: ``` <?xml version="1.0" encoding="UTF-8"?> <tt xmlns="link1" xmlns:prefix2="link2" prefix1:att1="att1"> <head> <styling> <style prefix1:att1="att1" prefix2:att2="att2" prefix2:att3="att3" prefix2:att4="att4" /> </styling> <layout /> </head> <body xmlns:prefix3="link3"> <div prefix1:att1="att1" prefix1:att2="att2"> <prefix3:info att1="att1" att2="att2" /> <p att1="att1" att2="att2" att3="att3"> <prefix3:status att1="att1" att2="att2" /> </p> </div> </body> </tt> ``` Desire output.xml: (same as caption.xml) ``` <?xml version="1.0" encoding="UTF-8"?> <tt xmlns="link1" xmlns:prefix2="link2" prefix1:att1="att1"> <head> <styling> <style prefix1:att1="att1" prefix2:att2="att2" prefix2:att3="att3" prefix2:att4="att4" /> </styling> <layout /> </head> <body xmlns:prefix3="link3"> <div prefix1:att1="att1" prefix1:att2="att2"> <prefix3:info att1="att1" att2="att2" /> <p att1="att1" att2="att2" att3="att3"> <prefix3:status att1="att1" att2="att2" /> Hello World. </p> </div> </body> </tt> ``` Thanks in advance to any help I may get to access this value and save it in setPhrase(String value) method.