Reputation: 521
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>
Upvotes: 3
Views: 14796
Reputation: 80593
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:
StationList
should be stationList
, for example).@XMLRootElement
.List
, instead of ArrayList
).@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
}
Upvotes: 1
Reputation: 1586
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;
}
}
Upvotes: 2