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.

Original source