1. 程式人生 > >java解析XML之DOM解析和SAX解析(包含CDATA的問題)

java解析XML之DOM解析和SAX解析(包含CDATA的問題)

  Dom解析功能強大,可增刪改查,操作時會將XML文件讀到記憶體,因此適用於小文件;
  SAX解析是從頭到尾逐行逐個元素解析,修改較為不便,但適用於只讀的大文件;SAX採用事件驅動的方式解析XML。如同在電影院看電影一樣,從頭到尾看一遍,不能回退(Dom可來來回回讀取),在看電影的過程中,每遇到一個情節,都會呼叫大腦去接收處理這些資訊。SAX也是相同的原理,每遇到一個元素節點,都會呼叫相應的方法來處理。在SAX的解析過程中,讀取到文件開頭、文件結尾,元素的開頭和元素結尾都會呼叫相應方法,我們可以在這些方法中進行相應事件處理。
github專案地址:https://github.com/Snailclimb/XML

github
Students.xml

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

<Students> 
  <Student num="001"> 
    <name>小明</name>  
    <age>20</age>  
    <subject><![CDATA[數學&英語]]></subject>  
    <sport>籃球</sport> 
  </Student>  
  <Student
num="002">
<name>小紅</name> <age>21</age> <subject><![CDATA[數學&英語]]></subject> <sport>籃球</sport> </Student> <Student num="003"> <name>小藍</name> <age>23</age> <subject
>
<![CDATA[數學&英語]]></subject> <sport>籃球</sport> </Student> <Student num="004"> <name>小白</name> <age>19</age> <subject><![CDATA[數學&英語]]></subject> <sport>籃球</sport> </Student> <Student num="005"> <name>小林子</name> <age>18</age> <subject><![CDATA[數學&英語]]></subject> <sport>籃球</sport> </Student> <Student num="006"> <name>小東子</name> <age>20</age> <subject><![CDATA[數學&英語]]></subject> <sport>籃球</sport> </Student> <Student num="007"> <name>小左子</name> <age>21</age> <subject><![CDATA[數學&英語]]></subject> <sport>籃球</sport> </Student> <Student num="008"> <name>小張</name> <age>22</age> <subject><![CDATA[數學&英語]]></subject> </Student> <Student num="009"> <name>小明</name> <age>23</age> <subject><![CDATA[數學&英語]]></subject> <sport>籃球</sport> </Student> <Student num="010"> <name>小明</name> <age>20</age> <subject><![CDATA[數學&英語]]></subject> <sport>籃球</sport> </Student> </Students>

DOM解析

package cn.yangtze.domtext;

import java.io.IOException;

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

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

public class DomPractice {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        // 建立一個DocumentBuilderFactory的物件
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        // 建立一個DocumentBuilder的物件
        try {
            // 建立DocumentBuilder物件
            DocumentBuilder db = dbf.newDocumentBuilder();
            // 通過DocumentBuilder物件的parser方法載入books.xml檔案到當前專案下
            Document document = db.parse("Students.xml");
            // 獲取所有Student節點的集合
            NodeList StudentList = document.getElementsByTagName("Student");
            // 通過nodelist的getLength()方法可以獲取StudentList的長度
            System.out.println("DOM解析開始...");
            // 遍歷每一個Student節點
            for (int i = 0; i < StudentList.getLength(); i++) {
                System.out.println("開始解析第" + (i + 1) + "個學生");
                // 通過 item(i)方法 獲取一個Student節點,nodelist的索引值從0開始
                Node book = StudentList.item(i);
                // 獲取Student節點的所有屬性集合
                NamedNodeMap attrs = book.getAttributes();
                // 遍歷Student的屬性
                for (int j = 0; j < attrs.getLength(); j++) {
                    // 通過item(index)方法獲取Student節點的某一個屬性
                    Node attr = attrs.item(j);

                    // 輸出學生的屬性名和屬性值
                    System.out.println(attr.getNodeName() + ":" + attr.getNodeValue());
                }
                NodeList childNodes = book.getChildNodes();
                // 遍歷childNodes獲取每個節點的節點名和節點值
                for (int k = 0; k < childNodes.getLength(); k++) {
                    // 區分出text型別的node以及element型別的node
                    if (childNodes.item(k).getNodeType() == Node.ELEMENT_NODE) {

                        // 輸出子節點的屬性名和屬性值
                        System.out.println(childNodes.item(k).getNodeName() + ":"
                                + childNodes.item(k).getFirstChild().getNodeValue());

                    }

                }

            }
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("DOM解析結束...");
    }
}

SAX解析
SAXParserHandler.java

package cn.yangtze.saxtext;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class SAXParserHandler extends DefaultHandler {
    private int StudentIndex = 0;

    // 解析開始的標誌
    @Override
    public void startDocument() throws SAXException {
        System.out.println("SAX解析開始...");
    }

    // 解析結束的標誌
    @Override
    public void endDocument() throws SAXException {
        System.out.println("SAX解析結束...");
    }

    // 用來遍歷XML檔案的開始標籤
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        // 呼叫DefaultHandler類的startElement方法
        super.startElement(uri, localName, qName, attributes);
        // 開始解析Student元素節點
        if (qName.equals("Student")) {
            ++StudentIndex;
            System.out.println("開始解析第" + StudentIndex + "個學生");
            //輸出XML屬性,也就是XML檔案中的num屬性,注意在因使用屬性而引起的一些問題:
            /*1 ,屬性無法包含多重的值(元素可以)
            2,屬性無法描述樹結構(元素可以)
            3,屬性不易擴充套件(為未來的變化)
            4,屬性難以閱讀和維護
            5,請儘量使用元素來描述資料。而僅僅使用屬性來提供與資料無關的資訊。*/
            for (int i = 0; i < attributes.getLength(); ++i) {
                System.out.println(attributes.getQName(i) + ":" + attributes.getValue(i));
            }
        } else if (!qName.equals("Students")) {
            System.out.print(qName + ":");//輸出元素值
        }
    }

    // 用來遍歷XML檔案的結束標籤
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        super.endElement(uri, localName, qName);
        // 判斷一個學生是否解析完
        if (qName.equals("Student")) {
            System.out.println("結束解析第" + StudentIndex + "個學生");
        } 
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        super.characters(ch, start, length);
        String text = new String(ch, start, length);
        if (!text.trim().equals("")) {
            System.out.println(text);
        } // if
    }
}

SAXDemo.java

//SAX解析XML
package cn.yangtze.saxtext;

import java.io.File;
import java.io.IOException;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;

public class SAXDemo {
    public static void main(String[] args) {
        File file =new File("Students.xml");
        try {
            // 通過SAXParserFactory的靜態方法newInstance()方法獲取SAXParserFactory例項物件factory
            SAXParserFactory factory = SAXParserFactory.newInstance();
            // 通過SAXParserFactory例項的newSAXParser()方法返回SAXParser例項parser
            SAXParser saxParser = factory.newSAXParser();
            // 定義SAXParserHandler物件
            SAXParserHandler handler = new SAXParserHandler();
            // 解析XML文件
            saxParser.parse(file, handler);
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}