Java——DOM解析XML文件

Java中解析XML文件的方式有四种,分别是:

  1. DOM解析
  2. SAX解析
  3. DOM4J解析
  4. JDOM解析

其中,DOM和SAX是Java内置提供的解析方式,无需引用JAR包;而DOM4J和JDOM则是第三方提供的,需要引入相应JAR包才可使用。

本篇文章介绍DOM解析。


DOM解析的基本步骤如下:

  1. 创建DocumentBuilderFactory的对象(通过newInstance()方法)
  2. 创建DocumentBuilder的对象(通过DocumentBuilderFactory的newDocumentBuilder()方法)
  3. 通过DocumentBuilder对象的parse()方法对xml文件进行解析

下面开始动手操作:

首先,先创建一个xml文件。这里以books.xml为例,记录两本书的信息。

books.xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
    <book id="1">
        <name>冰与火之歌</name>
        <author>乔治马丁</author>
        <price>89</price>
    </book>
    <book id="2">
        <name>安徒生通话</name>
        <author>安徒生</author>
        <price>24</price>
    </book>
</bookstore>

该XML文件的根节点为bookstore,可以理解为这个文件就相当于是一家书店,而其中每个book节点都是一本书,文件中存储了这些书的书名、作者、价格信息。


为了与books.xml文件对应,需要定义一个Book类来封装书的那些属性。

package domain;

public class Book {
    private String name;
    private String author;
    private float price;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Book [name=" + name + ", author=" + author + ", price=" + price + "]";
    }

}

准备工作做完了,下面就该对XML文件进行解析。

第一步:创建DocumentBuilderFactory对象

//创建DocumentBuilderFactory的对象
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

第二步:创建DocumentBuilder对象

//通过DocumentBuilderFactory创建一个DocumentBuilder对象
DocumentBuilder builder = factory.newDocumentBuilder();

第三步:通过DocumentBuilder对象的parse()方法对XML文件进行解析

//通过DocumentBuilder对象的parse方法解析xml文件,并用Document对象接收
Document document = builder.parse(file);

接下来,就该获取XML文件中的内容了。

由于我们需要获取每一本书的信息,所以我们可以对每个book节点进行解析。

使用getElementsByTagName()方法,可以获取所有指定名称的节点。这里我们需要获取所有的book节点:

//通过document.getElementsByTagName获取所有名为book的节点的集合
NodeList bookList = document.getElementsByTagName("book");

通过getLength()方法,可以获得book节点集合的长度,相当于总共有多少本书。

System.out.println("共有 " + bookList.getLength() + " 本书");

接下来,需要遍历所有的书,并记录下他们的信息。

在XML文件中可以看到,我们为每本书指定了一个id属性,现在我们来获取这个id。由于id是book节点的属性,所以我们需要获取book的所有属性。

通过item()方法可以获得一个NodeList中的某个元素。

Node book = bookList.item(0);//获取NodeList中的第一个元素,即第一本书

通过getAttributes可获取该书的所有属性,可以对这些属性进行遍历并打印这些属性:

NamedNodeMap attrs = book.getAttributes();
for(int k=0; k<attrs.getLength(); ++k){
    Node node = attrs.item(k);
    System.out.println(node.getNodeName() + " : " + node.getNodeValue());
}

这样,book节点的属性就获取到了。


接下来,获取book的所有子节点(即书的属性)。

通过getChildNodes()方法可以获取当前节点的所有子节点的集合:

NodeList child = book.getChildNodes();

接下来获取每个子节点的属性。

遍历每个子节点,并获取他们的节点名称和值:

for(int j=0; j<child.getLength(); ++j){
    Node node = child.item(j);
    //过滤掉换行、空格等text类型的节点,只保留带标签的元素节点
    if(node.getNodeType() == Node.ELEMENT_NODE){
    //标签之间的内容被认为是该标签的子节点,所以需要使用node.getFirstChild()获取到这个子节点的第一个孩子节点后再获取其值,并封装到一个Book类的对象中即可。
        switch(node.getNodeName()){
            case "name" :
                aBook.setName(node.getFirstChild().getNodeValue());
                break;
            case "author" :
                aBook.setAuthor(node.getFirstChild().getNodeValue());
                break;
            case "price":
                aBook.setPrice(Float.valueOf(node.getFirstChild().getNodeValue()));
                break;
        }

        //使用getTextContent()方法可获取该标签节点下的所有子节点内容
//      System.out.println(node.getNodeName() + " : " + node.getTextContent());
    }
}

完整的程序代码:

package utils;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import domain.Book;

public class ParseUtil {

    /*
     * DOM解析
     * */
    public static void parseByDOM(File file){
        //创建DocumentBuilderFactory的对象
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        try {
            //通过DocumentBuilderFactory创建一个DocumentBuilder对象
            DocumentBuilder builder = factory.newDocumentBuilder();

            //通过DocumentBuilder对象的parse方法解析xml文件,并用Document对象接收
            Document document = builder.parse(file);

            //通过document.getElementsByTagName获取所有名为book的节点的集合
            NodeList bookList = document.getElementsByTagName("book");

            System.out.println("共有 " + bookList.getLength() + " 本书");

            //遍历每一本书
            for(int i=0; i<bookList.getLength(); ++i){
                System.out.println("第" + (i+1) + "本书:");
                Node book = bookList.item(i);

                Book aBook = new Book();

                //获取book节点的所有属性
                NamedNodeMap attrs = book.getAttributes();
                for(int k=0; k<attrs.getLength(); ++k){
                    Node node = attrs.item(k);
                    System.out.println(node.getNodeName() + " : " + node.getNodeValue());
                }

                //获取book节点的所有子节点的 名及值
                NodeList child = book.getChildNodes();
                for(int j=0; j<child.getLength(); ++j){
                    Node node = child.item(j);
                    //过滤掉换行、空格等text类型的节点,只保留带标签的元素节点
                    if(node.getNodeType() == Node.ELEMENT_NODE){
                        //标签之间的内容被认为是该标签的子节点,所以需要使用node.getFirstChild()获取到这个子节点的第一个孩子节点后再获取其值
                        switch(node.getNodeName()){
                            case "name" :
                                aBook.setName(node.getFirstChild().getNodeValue());
                                break;
                            case "author" :
                                aBook.setAuthor(node.getFirstChild().getNodeValue());
                                break;
                            case "price":
                                aBook.setPrice(Float.valueOf(node.getFirstChild().getNodeValue()));
                                break;
                        }

                        //使用getTextContent()方法可获取该标签节点下的所有子节点内容
//                      System.out.println(node.getNodeName() + " : " + node.getTextContent());
                    }
                }
                System.out.println(aBook);
            }

        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

输出的结果:

共有 2 本书
第1本书:
id : 1
Book [name=冰与火之歌, author=乔治马丁, price=89.0]2本书:
id : 2
Book [name=安徒生童话, author=安徒生, price=24.0]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值