天天看點

XML的SAX解析以及DOM解析和SAX解析差別

前言:

XML解析工具

DOM解析原理:
    1)JAXP (oracle-Sun公司官方)
    2)JDOM工具(非官方)
    3)Dom4J工具(非官方)
    三大架構(預設讀取xml的工具就是Dom4j)
    .......

SAX解析原理:
    1)Sax解析工具(oracle-sun公司官方)           

老樣子,三個問題:

SAX解析是什麼?
SAX怎麼用?
SAX運用場景?           

SAX是什麼?

也是用來解析XML的

SAX解析工具- 内置在jdk中。org.xml.sax.*

SAX運用場景?

DOM解析原理:一次性把xml文檔加載進記憶體,然後在記憶體中建構Document樹。
對記憶體要求比較要。    
缺點: 不适合讀取大容量的xml檔案,容易導緻記憶體溢出。
           

SAX解析原理: 加載一點,讀取一點,處理一點。對記憶體要求比較低。

SAX解析工具核心:

核心的API:

SAXParser類: 用于讀取和解析xml檔案對象
parse(File f, DefaultHandler dh)方法: 解析xml檔案           
參數一: File:表示 讀取的xml檔案。

參數二: DefaultHandler: SAX事件處理程式。使用DefaultHandler的子類

第一步:建立對象

//1.建立SAXParser對象
    SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
        
        //2.調用parse方法
        /**
         * 參數一: xml文檔
         * 參數二: DefaultHandler的子類   MyDefaultHandler()為自定義
         */
    parser.parse(new File(".\\src\\Go\\person.xml"),  
    new MyDefaultHandler());           

注意:

這裡建立SAXParser對象 不能直接通過構造函數來創造,因為用到了單例工廠模式。

連結:類 SAXParser的jdk文檔

是以建立一個SAXParser對象 需要:

SAXParserFactory.newInstance().newSAXParser();

DefaultHandler類的API:後三個最重要

  1. void startDocument() : 在讀到文檔開始時調用
  1. void endDocument() :在讀到文檔結束時調用
  2. void startElement(String uri, String localName, String qName, Attributes attributes) :

    讀到開始标簽時調用

  3. void endElement(String uri, String localName, String qName) :讀到結束标簽時調用
  4. void characters(char[] ch, int start, int length) : 讀到文本内容時調用

第二步:自定義類繼承DefaultHandler重寫方法

這些都是要重寫的 舉個例子:

public class MyDefaultHandler extends DefaultHandler {
    
    /**
     * 開始文檔時調用
     */
    @Override
    public void startDocument() throws SAXException {
        System.out.println("MyDefaultHandler.startDocument()");
    }
    
    /**
     * 開始标簽時調用
     * @param qName: 表示開始标簽的标簽名
     * @param attributes: 表示開始标簽内包含的屬性清單
     */
    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        System.out.println("MyDefaultHandler.startElement()-->"+qName);
    }
    
    /**
     * 結束标簽時調用
     * @param qName: 結束标簽的标簽名稱
     */
    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        System.out.println("MyDefaultHandler.endElement()-->"+qName);
    }
    
    /**
     * 讀到文本内容的時調用
     * @param ch: 表示目前讀完的所有文本内容
     * @param start: 表示目前文本内容的開始位置
     * @param length: 表示目前文本内容的長度
     * char[](                                       張三              20)   100
     *                              98 2   
     */ 
    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        //得到目前文本内容
        String content = new String(ch,start,length);
        System.out.println("MyDefaultHandler.characters()-->"+content);
    }
    
    /**
     * 結束文檔時調用
     */
    @Override
    public void endDocument() throws SAXException {
        System.out.println("MyDefaultHandler.endDocument()");
    }
    
}           

xml樣例:

<?xml version="1.0" encoding="utf-8"?>
<contactList>
    <contact id="001" name="eric">
        <name>張三</name>
        <age>20</age>
        <phone>134222223333</phone>
        <email>[email protected]</email>
        <qq>432221111</qq>
    </contact>
    <contact id="002" name="jacky">
        <name>eric</name>
        <age>20</age>
        <phone>134222225555</phone>
        <email>[email protected]</email>
        <qq>432222222</qq>
    </contact>
</contactList>           

結果:

MyDefaultHandler.startDocument()
MyDefaultHandler.startElement()-->contactList
MyDefaultHandler.characters()-->
    
MyDefaultHandler.startElement()-->contact
MyDefaultHandler.characters()-->
        
MyDefaultHandler.startElement()-->name
MyDefaultHandler.characters()-->張三
MyDefaultHandler.endElement()-->name
MyDefaultHandler.characters()-->
        
MyDefaultHandler.startElement()-->age
MyDefaultHandler.characters()-->20
MyDefaultHandler.endElement()-->age
MyDefaultHandler.characters()-->
        
MyDefaultHandler.startElement()-->phone
MyDefaultHandler.characters()-->134222223333
MyDefaultHandler.endElement()-->phone
MyDefaultHandler.characters()-->
        
MyDefaultHandler.startElement()-->email
MyDefaultHandler.characters()-->[email protected]
MyDefaultHandler.endElement()-->email
MyDefaultHandler.characters()-->
        
MyDefaultHandler.startElement()-->qq
MyDefaultHandler.characters()-->432221111
MyDefaultHandler.endElement()-->qq
MyDefaultHandler.characters()-->
    
MyDefaultHandler.endElement()-->contact
MyDefaultHandler.characters()-->
    
MyDefaultHandler.startElement()-->contact
MyDefaultHandler.characters()-->
        
MyDefaultHandler.startElement()-->name
MyDefaultHandler.characters()-->eric
MyDefaultHandler.endElement()-->name
MyDefaultHandler.characters()-->
        
MyDefaultHandler.startElement()-->age
MyDefaultHandler.characters()-->20
MyDefaultHandler.endElement()-->age
MyDefaultHandler.characters()-->
        
MyDefaultHandler.startElement()-->phone
MyDefaultHandler.characters()-->134222225555
MyDefaultHandler.endElement()-->phone
MyDefaultHandler.characters()-->
        
MyDefaultHandler.startElement()-->email
MyDefaultHandler.characters()-->[email protected]
MyDefaultHandler.endElement()-->email
MyDefaultHandler.characters()-->
        
MyDefaultHandler.startElement()-->qq
MyDefaultHandler.characters()-->432222222
MyDefaultHandler.endElement()-->qq
MyDefaultHandler.characters()-->
    
MyDefaultHandler.endElement()-->contact
MyDefaultHandler.characters()-->

MyDefaultHandler.endElement()-->contactList
MyDefaultHandler.endDocument()
           

問題:MyDefaultHandler.characters()-->空白 ?

答:

<contactList>
    <contact>
    之間也是有文本的 是換行和空格 被characters方法讀取了。
           

來看一下SAX解析XML的流程圖:(圖檔來自傳智播客)

回到開頭

SAX解析原理: 加載一點,讀取一點,處理一點。對記憶體要求比較低。

總結:

==================DOM解析 vs SAX解析 ============================

DOM解析 :

原理: 一次性加載xml文檔,不适合大容量的檔案讀取
DOM解析可以任意進行增删改成
DOM解析任意讀取任何位置的資料,甚至往回讀
DOM解析面向對象的程式設計方法(Node,Element,Attribute),  
Java開發者編碼比較簡單。           

SAX解析 :

原理: 加載一點,讀取一點,處理一點。适合大容量檔案的讀取
SAX解析隻能讀取
SAX解析隻能從上往下,按順序讀取,不能往回讀
SAX解析基于事件的程式設計方法。java開發編碼相對複雜。           

XML操作:

1)Dom4j修改xml文檔
                 new XMLWrier();
                    ......
            2)xPath技術: 快速查詢xml節點
                    selectNodes()
                    selectSinglNode();    
            3)  SAX解析
                    SAXParser parse
                        parser()
                DefaultHandler類:
                        startElement();
                        characters();
                        endElement();