Question

I am trying to use the JAXB Unmarshaller to translate an xml document into a java object tree.

The XML document looks like this:

<Levels>
    <Level>
        <Solution>
            <Piece x="0" y="1">
                <Shape/>
                <Color/>
            </Piece>
            <Piece x="0" y="1">
                <Shape/>
                <Color/>
            </Piece>
        </Solution>
        <Clues>
            <Clue>
                <Piece x="0" y="0">
                    <Shape/>
                    <Color/>
                </Piece>
            </Clue>
            <Clue>
                <Piece x="0" y="0">
                    <Shape/>
                    <Color/>
                </Piece>
            </Clue>
        </Clues>
    </Level>
</Levels>

I created very basic classes to hold each component:

Levels.java:

@XmlRootElement
public class Levels {

    private List<Level> levels = new ArrayList<Level>();

    @XmlElementRef(name="Level")
    public List<Level> getLevels() {
        return levels;
    }

    public void setLevels(List<Level> levels) {
        this.levels = levels;
    }
}

Level.java:

@XmlRootElement(name="Levels")
public class Level {

    private Solution solution = new Solution();
    private Clues clues = new Clues();

    @XmlElementRef(name="Solution")
    public Solution getSolution() {
            return solution;
    }

        public void setSolution(Solution solution) {
        this.solution = solution;
    }

    @XmlElementRef(name="Clues")
    public Clues getClues() {
        return clues;
    }

    public void setClues(Clues clues) {
        this.clues = clues;
    }
}

The rest of the classes are formatted the same as these(same annotations and only getter and setter methods)

The code I use to unmarshal the xml is:

File file = new File("res/levelTest.xml");

JAXBContext jaxbContext = JAXBContext.newInstance(Levels.class);        
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

Object o = jaxbUnmarshaller.unmarshal(file);        
System.out.println(o);

The problem I am getting is that when I print the object, it prints newXML.Solution@*** not newXML.Levels@*** which is the root element. This means that the unmarshaller is returning an element other than the root element. I have searched google and stack overflow but I couldn't find an explanation for this.

Any help is appreciated.

Was it helpful?

Solution

You've got an annotation conflict with your top-level class name and the name placed on the Level class.

You've annotated your Level class with the XmlElementRoot set to "Levels", which is actually the root element for your Levels class. Since you didn't specify it explicitly in your annotation for that class, the JAXB binding is returning a different mapping for your classes.

I created a quick mockup of your program, and was able to get it working properly with the following:

Levels class:

@XmlRootElement(name="Levels")
public class Levels {


    private List<Level> levels = new ArrayList<Level>();

    @XmlElementRef(name="Level")
    public List<Level> getLevels() {
        return levels;
    }

    public void setLevels(List<Level> levels) {
        this.levels = levels;
    }
}

Level class:

@XmlRootElement(name="Level")
public class Level {

    private Solution solution = new Solution();
    private Clues clues = new Clues();

    @XmlElementRef(name="Solution")
    public Solution getSolution() {
        return solution;
    }

    public void setSolution(Solution solution) {
        this.solution = solution;
    }

    @XmlElementRef(name="Clues")
    public Clues getClues() {
        return clues;
    }

    public void setClues(Clues clues) {
        this.clues = clues;
    }
}

Clues class (empty because I just needed a class definition):

@XmlRootElement
public class Clues {
}

Solution class (same as above):

@XmlRootElement
public class Solution {
}

Running the code using your input produces:

Levels@***
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top