2013-04-14 45 views
3

我想使用DOM解析器解析XML文件。 XML文件包含按名稱,FAA標識符,緯度/經度和URL列出的機場列表。下面是它的一個片段:包含每個信息在Java中使用DOM解析器創建對象?

<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); 


} 

} 

回答

3

您目前擁有的是全局類變量。你需要一個Object包含的變量:

public class Airport { 
    String stationId; 
    String state; 
    String stationName; 
    double latitude; 
    double longitude; 
    String url; 

    //getters/setters etc 
} 

現在,在你的類

final List<Airport> airports = new LinkedList<Airport>(); 

最後創建並在循環

增加機場的情況下,到 List頂部創建機場的 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 POJOs中,我真的會推薦使用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> 

我將模式編譯爲一個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> 
+0

感謝您的幫助,但我有更多的問題。我無法從DOM內解析變量(stationName等)。我想我誤解了新的機場等級和名單。我在哪裏放置/修改它們以便我可以修復這些錯誤?我也創建了getters/setters。我需要一個構造函數嗎?基本上,DOM不能再訪問我的變量。 – David

+0

您無法解析DOM內部的變量 - 您需要使用getters/setters - 如上例所示。一個'Object'總是有一個[noargs構造函數](http://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html),除非明確提供 - 因爲你不需要任何東西,noargs構造函數沒有必要定義一個。這是[Java Bean]的示例(http://en.wikipedia.org/wiki/JavaBeans)。 –

+0

我們不能使用java方法爲每個字段設置別名嗎?或註釋? –

0

可以使用POJO類保存電臺性能。

該程序使用BeanUtils將屬性填充到bean中,而不是使用每個屬性的setter/getter。

一件事是在你的XML缺少的是

<?xml version="1.0" encoding="UTF-8"?> 

,並附如下圖所示,以形成有效的XML,說

根元素在外部stations標籤的所有station必須是良構

<?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(); 
    } 

}