Создавать объекты из DOM-парсера в Java?
Я пытаюсь проанализировать файл XML с помощью анализатора DOM. Файл XML содержит список аэропортов по названию, идентификатору FAA, широте / долготе и URL. Вот фрагмент этого:
<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>
Я пытаюсь создать объекты (по одному для каждого аэропорта), содержащие информацию о каждом проанализированном аэропорту, чтобы я мог отображать каждый аэропорт только по названию. Остальная информация об аэропорте будет использована позже в проекте.
Может кто-нибудь сказать мне, как я могу создавать и создавать экземпляры объектов из информации, предоставленной этим анализатором DOM, чтобы я мог отображать только название каждого аэропорта?
Вот мой код:
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class Test {
//initialize variables
String station_id;
String state;
String station_name;
double latitude;
double longitude;
String html_url;
//Here is my constructor, I wish to instantiate these values with
//those of obtained by the DOM parser
Test(){
station_id = this.station_id;
state = this.state;
station_name = this.station_name;
latitude = this.latitude;
longitude = this.longitude;
html_url = this.html_url;
}
//Method for DOM Parser
public void readXML(){
try {
//new xml file and Read
File file1 = new File("src/flwxindex3.xml");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(file1);
doc.getDocumentElement().normalize();
NodeList nodeList = doc.getElementsByTagName("station");
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if(node.getNodeType() == Node.ELEMENT_NODE){
Element first = (Element) node;
station_id = first.getElementsByTagName("station_id").item(0).getTextContent();
state = first.getElementsByTagName("state").item(0).getTextContent();
station_name = first.getElementsByTagName("station_name").item(0).getTextContent();
latitude = Double.parseDouble(first.getElementsByTagName("latitude").item(0).getTextContent());
longitude = Double.parseDouble(first.getElementsByTagName("longitude").item(0).getTextContent());
html_url = first.getElementsByTagName("station_id").item(0).getTextContent();
}
/*These are just test to see if the actually worked
*
System.out.println(station_id);
System.out.println(state);
System.out.println(station_name);
System.out.println(latitude);
System.out.println(longitude);
System.out.println(html_url);
*/
}
} catch (Exception e) {
System.out.println("XML Pasing Excpetion = " + e);
}
}
public static void main(String[] args) {
//Create new object and call the DOM Parser method
Test test1 = new Test();
test1.readXML();
//System.out.println(test1.station_name);
}
}
2 ответа
В настоящее время у вас есть переменные, которые являются глобальными для вашего класса. Вам нужен Object
содержать ваши переменные:
public class Airport {
String stationId;
String state;
String stationName;
double latitude;
double longitude;
String url;
//getters/setters etc
}
Теперь создайте List
из ваших аэропортов на вершине вашего класса
final List<Airport> airports = new LinkedList<Airport>();
Наконец, создайте и добавьте экземпляры аэропорта в List
в вашей петле
if(node.getNodeType() == Node.ELEMENT_NODE){
final Element first = (Element) node;
final Airport airport = new Airport();
airport.setStationId(first.getElementsByTagName("station_id").item(0).getTextContent());
airport.setState(first.getElementsByTagName("state").item(0).getTextContent());
//etc
airports.add(airport);
}
И обойти аэропорты и показать имена, просто
for(final Airport airport : airports) {
System.out.println(airport.getStationName());
}
Честно говоря, все это немного грязно. Я действительно рекомендую использовать JAXB, если вы хотите демонтировать ваш XML в Java POJO.
Вот быстрый пример использования схемы XML, maven-jaxb2-plugin и JAXB.
С небольшой подготовкой вы можете создать свой список Airport
используя только следующий код (Airport
стал Station
так как это ваше имя элемента XML).
public static void main(String[] args) throws InterruptedException, JAXBException {
final JAXBContext jaxbc = JAXBContext.newInstance(Stations.class);
final Unmarshaller unmarshaller = jaxbc.createUnmarshaller();
final Stations stations = (Stations) unmarshaller.unmarshal(Thread.currentThread().getContextClassLoader().getResource("airports.xml"));
for (final Station station : stations.getStation()) {
System.out.println(station.getStationName());
}
}
Выход:
Nausori
Crestview, Sikes Airport
Для того, чтобы это работало, я создал схему XML, чтобы определить формат файла XML.
<xs:element name="stations">
<xs:complexType>
<xs:sequence>
<xs:element name="station" minOccurs="1" maxOccurs="unbounded">
<xs:complexType>
<xs:all>
<xs:element name="station_id" type="xs:string"/>
<xs:element name="state" type="xs:string"/>
<xs:element name="station_name" type="xs:string"/>
<xs:element name="latitude" type="xs:decimal"/>
<xs:element name="longitude" type="xs:decimal"/>
<xs:element name="html_url" type="xs:anyURI"/>
<xs:element name="rss_url" type="xs:anyURI"/>
<xs:element name="xml_url" type="xs:anyURI"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
Определяет формат вашего XML-файла. Обратите внимание, что у него есть stations
тег, который оборачивает ваши две метки станции. Вот пример xml
<stations>
<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>
</stations>
Я скомпилировал схему в класс Java, используя следующее в моем pom.xml - используя maven. Если вы не используете maven, вы можете вызвать xjc из командной строки.
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.8.0</version>
<configuration>
<schemaDirectory>src/main/resources/</schemaDirectory>
<generatePackage>com.boris.airport</generatePackage>
</configuration>
<executions>
<execution>
<id>generate</id>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
Вы можете использовать класс POJO для хранения свойств станции.
Эта программа использует BeanUtils
заполнять свойства в bean-компоненте, а не использовать setter/getter для каждого свойства.
Еще одна вещь, которая отсутствует в вашем XML
<?xml version="1.0" encoding="UTF-8"?>
и приложить все station
во внешнем stations
тег, как показано ниже, чтобы сформировать правильный XML, который говорит
корневой элемент должен быть правильно сформирован
<?xml version="1.0" encoding="UTF-8"?>
<stations>
<station>
...
</station>
<station>
...
</station>
</stations>
Вот код
import java.io.FileInputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.commons.beanutils.BeanUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class DOMParsarDemo3 {
protected DocumentBuilder docBuilder;
protected Element root;
private static List<AirportStation> stations = new ArrayList<AirportStation>();
public DOMParsarDemo3() throws Exception {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
docBuilder = dbf.newDocumentBuilder();
}
public void parse(String file) throws Exception {
Document doc = docBuilder.parse(new FileInputStream(file));
root = doc.getDocumentElement();
System.out.println("root element is :" + root.getNodeName());
}
public void printAllElements() throws Exception {
printElement(root);
}
public void printElement(Node node) {
if (node.getNodeType() != Node.TEXT_NODE) {
Node child = node.getFirstChild();
while (child != null) {
if ("station".equals(child.getNodeName())) {
NodeList station = child.getChildNodes();
Map<String, String> map = new HashMap<String, String>();
for (int i = 0; i < station.getLength(); i++) {
Node s = station.item(i);
if (s.getNodeType() == Node.ELEMENT_NODE) {
map.put(s.getNodeName(), s.getChildNodes().item(0).getNodeValue());
}
}
AirportStation airportStation = new AirportStation();
try {
BeanUtils.populate(airportStation, map);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
stations.add(airportStation);
}
printElement(child);
child = child.getNextSibling();
}
}
}
public static void main(String args[]) throws Exception {
DOMParsarDemo3 demo = new DOMParsarDemo3();
demo.parse("resources/abc2.xml");
demo.printAllElements();
for (AirportStation airportStation : stations) {
System.out.println(airportStation);
}
}
}
POJO
import java.io.Serializable;
public class AirportStation implements Serializable {
private static final long serialVersionUID = 1L;
public AirportStation() {
}
private String station_id;
private String state;
private String station_name;
private String latitude;
private String longitude;
private String html_url;
private String rss_url;
private String xml_url;
public String getStation_id() {
return station_id;
}
public void setStation_id(String station_id) {
this.station_id = station_id;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getStation_name() {
return station_name;
}
public void setStation_name(String station_name) {
this.station_name = station_name;
}
public String getLatitude() {
return latitude;
}
public void setLatitude(String latitude) {
this.latitude = latitude;
}
public String getLongitude() {
return longitude;
}
public void setLongitude(String longitude) {
this.longitude = longitude;
}
public String getHtml_url() {
return html_url;
}
public void setHtml_url(String html_url) {
this.html_url = html_url;
}
public String getRss_url() {
return rss_url;
}
public void setRss_url(String rss_url) {
this.rss_url = rss_url;
}
public String getXml_url() {
return xml_url;
}
public void setXml_url(String xml_url) {
this.xml_url = xml_url;
}
@Override
public String toString() {
return "station_id=" + getStation_id() + " station_name=" + getStation_name();
}
}