Problems with JAXB XML parsing

12,454

Solution 1

Assuming that wx_station_index is not a typo.

I've added some annotations to instruct jaxb on what part of the xml to map on what part of your code. Changing your StationListTest to the following should work a whole lot better.

import java.util.ArrayList;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

//create list for all weather stations
@XmlRootElement(name="wx_station_index")
public class StationListTest {

/**
 * @param args
 */
@XmlElement(name="station")    
private ArrayList<StationTest> StationList;

public StationListTest(){
    StationList=new ArrayList<StationTest>();
}

public void setStationListTest(ArrayList<StationTest> StationList){
    this.StationList = StationList;
}

public ArrayList<StationTest> getStationListTest(){
    return StationList;
}

}

Solution 2

There is a mismatch between the named property StationList on your class StationListTest and the implicit station list attribute in the XML document. This needs to be resolved by explicitly defining what elements of your XML the StationList property be populated from:

@XmlElement(name = "station")
private ArrayList<StationTest> StationList;

Some other quick notes:

  • You should follow Java naming patterns (camel case) for class and variable names. So StationList should be stationList, for example).
  • As a general rule you should annotate all your top level data classes with @XMLRootElement.
  • As a general rule, you should use the most generic form of a type when defining your Java class (List, instead of ArrayList).
  • You should indicate which other classes are involved in your mapping with an @XmlSeeAlso

The following class definitions work with your XML:

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

    @XmlElement(name = "station_id")
    String stationId;

    String state;

    @XmlElement(name = "station_name")
    String stationName;

    double latitude;
    double longitude;

    @XmlElement(name = "html_url")
    String htmlUrl;

    // Constructor, getters, setters
}

@XmlRootElement(name = "wx_station_index")
@XmlSeeAlso(value = StationTest.class)
@XmlAccessorType(XmlAccessType.FIELD)
public class StationListTest {
    @XmlElement(name = "station")
    private List<StationTest> stationList;

    // Constructors, getters, setters
}
Share:
12,454
David
Author by

David

Updated on June 04, 2022

Comments

  • David
    David almost 2 years

    I’m working on a project in which I will use JAXB to parse an XML file containing the following weather station information: Name, station ID, latitude/longitude, and url. Right now I intend to test everything by printing a weather station by name only. I have debugged my code but when I try to run: I get the following error:

    Exception in thread "main" javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"wx_station_index"). Expected elements are (none)

    Does anyone have an explanation? Any help would be appreciated. My code and sample of XML are posted below:

    //create criteria for weather station info
    @XmlRootElement
    @XmlAccessorType(XmlAccessType.FIELD)
    public class StationTest {
    
    /**
     * @param args
     */
    
    @XmlElement(name = "station_id")
    String station_id;
    
    @XmlElement(name = "state")
    String state;
    
    @XmlElement(name = "station_name")
    String stationName;
    
    @XmlElement(name = "latitude")
    double latitude;
    
    @XmlElement(name = "longitude")
    double longitude;
    
    @XmlElement(name = "html_url")
    String htmlUrl;
    
    public String getStationID(){
        return station_id;
    }
    
    public void setStationId(String station_id)
    {
         this.station_id = station_id;
    }
    
    public String getState(){
        return state;
    }
    
    public void setState(String state)
    {
         this.state = state;
    }
    
    public String getStationName(){
        return stationName;
    }
    
    public void setStationName(String station_name)
    {
         this.stationName = stationName;
    }
    
    public double getLatitude(){
        return latitude;
    }
    
    public void setLatitude(double latitude)
    {
         this.latitude = latitude;
    }
    
    public double getLongitude(){
        return longitude;
    }
    
    public void setLongitude(double longitude)
    {
         this.longitude = longitude;
    }
    
    public String getUrl(){
        return htmlUrl;
    }
    
    public void setUrl(String url){
        this.htmlUrl = htmlUrl;
    
    }
    

    } import java.util.ArrayList;

    import javax.xml.bind.annotation.XmlAccessorType;
    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlRootElement;
    import javax.xml.bind.annotation.XmlSeeAlso;
    import javax.xml.bind.annotation.XmlAccessType;
    
    //create list for all weather stations
    
    @XmlRootElement
    @XmlSeeAlso(value = StationTest.class)
    @XmlAccessorType(XmlAccessType.FIELD)
    public class StationListTest {
    
    /**
     * @param args
     */
    @XmlElement(name = "station")
    private ArrayList<StationTest> stationList;
    
    public void setStationListTest(ArrayList<StationTest> StationList){
        this.stationList = StationList;
    }
    
    public ArrayList<StationTest> getStationListTest(){
        return stationList;
    }
    
    }
    
    import java.util.ArrayList;
    
    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.JAXBException;
    import javax.xml.bind.Unmarshaller;
    
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.util.ArrayList;
    
     import javax.xml.bind.JAXBContext;
    import javax.xml.bind.JAXBException;
    import javax.xml.bind.Unmarshaller;
    
    //final Test of JAXB
    public class Test3 {
    
    /**
     * @param args
     */
    //read xml
    private static final String STATION_XML = "src/flwxindex3.xml";
    
    //main method
    public static void main(String[] args) throws InterruptedException, JAXBException, FileNotFoundException {
    
        //create list object
        ArrayList<StationTest> StationList = new ArrayList<StationTest>();
    
        final JAXBContext jaxbc = JAXBContext.newInstance(StationListTest.class);
        final Unmarshaller unmarshaller = jaxbc.createUnmarshaller();
    
        //create list for iteration, then iterate printing by name only
        StationListTest stationListTest = (StationListTest) unmarshaller.unmarshal(new FileReader(STATION_XML));
        ArrayList<StationTest> list = stationListTest.getStationListTest();
        //final StationListTest stations = (StationListTest) unmarshaller.unmarshal(Thread.currentThread().getContextClassLoader().getResource("src/flwxindex3.xml"));
        for (final StationTest station : list) {
            System.out.println(station.getStationName());
        }
    }
    

    }

    The actual xml as requested (Thought I included it, sorry):

    <?xml version="1.0" encoding="UTF-8"?>
    <wx_station_index>
        <credit>NOAA's National Weather Service</credit>
        <credit_URL>http://weather.gov/</credit_URL>
        <image>
                <url>http://weather.gov/images/xml_logo.gif</url>
                <title>NOAA's National Weather Service</title>
                <link>http://weather.gov</link>
        </image>
        <suggested_pickup>08:00 EST</suggested_pickup>
        <suggested_pickup_period>1140</suggested_pickup_period>
    
    <station>
        <station_id>NFNA</station_id>
        <state>FJ</state>
        <station_name>Nausori</station_name>
        <latitude>-18.05</latitude>
        <longitude>178.567</longitude>
        <html_url>http://weather.noaa.gov/weather/current/NFNA.html</html_url>
        <rss_url>http://weather.gov/xml/current_obs/NFNA.rss</rss_url>
        <xml_url>http://weather.gov/xml/current_obs/NFNA.xml</xml_url>
    </station>
    
    <station>
        <station_id>KCEW</station_id>
        <state>FL</state>
                <station_name>Crestview, Sikes Airport</station_name>
        <latitude>30.79</latitude>
        <longitude>-86.52</longitude>
                <html_url>http://weather.noaa.gov/weather/current/KCEW.html</html_url>
                <rss_url>http://weather.gov/xml/current_obs/KCEW.rss</rss_url>
                <xml_url>http://weather.gov/xml/current_obs/KCEW.xml</xml_url>
    </station>