How do I parse this XML in Java with JAXB?

Rolando picture Rolando · Nov 18, 2011 · Viewed 61.6k times · Source

I have the following XML, no XSD or schema with it that I want to parse to java object(s) using JAXB as I heard its better than SAX. Is there a way to accomplish this with annotations or a better way to do this? Does it make it so that i just need a single FosterHome class? I am having trouble finding how to do this any help is grateful.

I was originally thinking of having a FosterHome, Family, and Child class. Using JAXB, is having 3 classes no longer necessary? Im not sure how to deal with this as ChildID shows up in two different areas.

<?xml version="1.0" encoding="UTF-8"?>
<FosterHome>
    <Orphanage>Happy Days Daycare</Orphanage>
    <Location>Apple Street</Location>
    <Families>
        <Family>
            <ParentID>Adams</ParentID>
            <ChildList>
                <ChildID>Child1</ChildID>
                <ChildID>Child2</ChildID>
            </ChildList>
        </Family>
        <Family>
            <ParentID>Adams</ParentID>
            <ChildList>
                <ChildID>Child3</ChildID>
                <ChildID>Child4</ChildID>
            </ChildList>
        </Family>
    </Families>
    <RemainingChildList>
        <ChildID>Child5</ChildID>
        <ChildID>Child6</ChildID>
    </RemainingChildList>
</FosterHome>

Answer

bdoughan picture bdoughan · Nov 18, 2011

You could do the following. By leveraging @XmlElementWrapper you can reduce the amount of classes that you require:

FosterHome

package nov18;

import java.util.List;
import javax.xml.bind.annotation.*;

@XmlRootElement(name="FosterHome")
@XmlAccessorType(XmlAccessType.FIELD)
public class FosterHome {

    @XmlElement(name="Orphanage")
    private String orphanage;

    @XmlElement(name="Location")
    private String location;

    @XmlElementWrapper(name="Families")
    @XmlElement(name="Family")
    private List<Family> families;

    @XmlElementWrapper(name="RemainingChildList")
    @XmlElement(name="ChildID")
    private List<String> remainingChildren;

}

Family

package nov18;

import java.util.List;   
import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
public class Family {

    @XmlElement(name="ParentID")
    private String parentID;

    @XmlElementWrapper(name="ChildList")
    @XmlElement(name="ChildID")
    private List<String> childList;

}

Demo

package nov18;

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(FosterHome.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        FosterHome fosterHome = (FosterHome) unmarshaller.unmarshal(new File("src/nov18/input.xml"));

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(fosterHome, System.out);
    }

}

Input/Output

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<FosterHome>
    <Orphanage>Happy Days Daycare</Orphanage>
    <Location>Apple Street</Location>
    <Families>
        <Family>
            <ParentID>Adams</ParentID>
            <ChildList>
                <ChildID>Child1</ChildID>
                <ChildID>Child2</ChildID>
            </ChildList>
        </Family>
        <Family>
            <ParentID>Adams</ParentID>
            <ChildList>
                <ChildID>Child3</ChildID>
                <ChildID>Child4</ChildID>
            </ChildList>
        </Family>
    </Families>
    <RemainingChildList>
        <ChildID>Child5</ChildID>
        <ChildID>Child6</ChildID>
    </RemainingChildList>
</FosterHome>

For More Information


UPDATE

Is there I easy way I can iterate/print out all the ChildID in the Family class?

You could do the following:

    for(Family family : fosterHome.getFamilies()) {
        System.out.println(family.getParentID());
        for(String childID : family.getChildList()) {
            System.out.println("    " + childID);
        }
    }