3

我正在尝试使用 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);


}

}
4

2 回答 2

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>
于 2013-04-14T00:41:14.073 回答
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();
    }

}
于 2014-03-30T10:17:37.563 回答