我正在尝试使用DOM解析器解析XML文件。 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);
}
}
答案 0 :(得分:3)
您目前拥有适合您班级的全局变量。您需要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());
}
说实话,这有点乱。如果你想将你的XML解组为java POJO,我真的建议使用JAXB。
以下是使用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>
我在pom.xml中使用以下内容将模式编译为java类 - 使用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>
答案 1 :(得分:0)
您可以使用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();
}
}