【问题标题】:Create objects from DOM parser in Java?从 Java 中的 DOM 解析器创建对象?
【发布时间】:2013-04-06 08:09:01
【问题描述】:

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


}

}

【问题讨论】:

    标签: java xml-parsing domparser


    【解决方案1】:

    您可以使用 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();
        }
    
    }
    

    【讨论】:

      【解决方案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());
      }
      

      说实话,这有点混乱。如果您想将 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>
      

      【讨论】:

      • 感谢您的帮助,但我还有更多问题。我无法从 DOM 中解析变量(stationName 等)。我想我误解了新的 Airport Class 和 List。我在哪里放置/修改它们以便修复这些错误?我也创建了 getter/setter。我在任何地方都需要构造函数吗?基本上 DOM 不能再访问我的变量了。
      • 您无法从 DOM 内部解析变量 - 您需要使用 getter/setter - 如上例所示。 Object 总是有一个 noargs constructor 除非明确提供 - 因为你不需要任何东西,除了 noargs 构造函数,不需要定义一个。这是Java Bean 的示例。
      • 不能用java方法给每个字段设置别名吗?还是注解??
      猜你喜欢
      • 2014-12-25
      • 1970-01-01
      • 1970-01-01
      • 2013-04-04
      • 1970-01-01
      • 2021-06-23
      • 1970-01-01
      • 2013-04-06
      • 1970-01-01
      相关资源
      最近更新 更多