XML三種解析方式簡介以及JAVA實現

1、DOM

  DOM解析XML文件時,會將XML文件的所有內容讀取到內存中,然後允許您使用DOM API遍歷XML樹、檢索所需的數據。使用DOM操作XML的代碼看起來比較直觀,並且,在某些方面比基於SAX的實現更加簡單。但是,因爲DOM需要將 XML文件的所有內容讀取到內存中,所以內存的消耗比較大,特別對於運行Android的移動設備來說,因爲設備的資源比較寶貴,所以建議還是採用SAX 來解析XML文件,當然,如果XML文件的內容比較小採用DOM是可行的。
  在解析之後每一個元素都會以Node的形式在內存中進行存儲
  接下來使用代碼進行演示
  XML文件內容

<?xml version="1.0" encoding="UTF-8" standalone="no"?><書架>
    <>
        <名稱>平凡的世界</名稱>
        <作者>路遙</作者>
        <售價>50</售價>
    </>

    <>
        <名稱>人生哲思錄</名稱>
        <作者>周國平</作者>
        <售價>2000</售價>
    </>
</書架>

java代碼內容

package XML_Study.DOM_Study;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
 * DocumentBuilderFactory->DocumentBuilder->Document->NsodeList之後就可以進行改變了
 * @author SHUXIN
 */
public class DOM {
    @Test
    public void DOMfind() throws Exception{//進行查找元素的值
        DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = builderFactory.newDocumentBuilder();
        Document ducument = documentBuilder.parse("src/XML_Study/DOM_Study/DOM_Study.xml");
        NodeList nodeList = ducument.getElementsByTagName("售價");
        Node item1 = nodeList.item(1);
        String name=item1.getTextContent();
        System.out.println(name);
    }

    /**
     * 把整個文件加載到內存之中,之後通過樹的結構進行操作
     * DocumentBuilderFactory->DocumentBuilder->Document->NsodeList之後就可以進行改變內存了
     * TransformerFactory->Transformer->newTransformer.transform(domsouce, outputTarget);//一個是Source一個接口,使用實現類DomSource,以及StreamResult
     * @throws Exception
     */
    @Test
    public void modifDOM() throws Exception {//改變指定元素的內容
        DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = builderFactory.newDocumentBuilder();
        Document ducument = documentBuilder.parse("src/XML_Study/DOM_Study/DOM_Study.xml");
        NodeList nodeList = ducument.getElementsByTagName("售價");
        Node item1 = nodeList.item(1);
        item1.setTextContent("2000");

        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer newTransformer = transformerFactory.newTransformer();
        Source domsouce=new DOMSource(ducument);
        Result outputTarget=new StreamResult("src/XML_Study/DOM_Study/DOM_Study.xml");
        newTransformer.transform(domsouce, outputTarget);

    }
}

2.SAX

  SAX是一個解析速度快並且佔用內存少的xml解析器,非常適合用於Android等移動設備。SAX解析XML文件採用的是事件驅動,也就是說,它並不需要解析完整個文檔,在按內容順序解析文檔的過程中,SAX會判斷當前讀到的字符是否合法XML語法中的某部分,如果符合就會觸發事件。所謂事件,其實就是一些回調(callback)方法,這些方法(事件)定義在ContentHandler接口。
 這種方式解析是一種基於事件驅動的api,有兩個部分,解析器和事件處理器:
解析器就是XMLReader接口,負責讀取XML文檔,和向事件處理器發送事件(也是事件源),
事件處理器ContentHandler接口,負責對發送的事件響應和進行XML文檔處理。對於SAX解析方式可以使用ContentHandle的實現類
以下是SAX的圖解,建議之後通過代碼對照理解
這裏寫圖片描述
SAX常用事件如下:
startDocument() —-文檔開始事件
startElement() —-元素開始事件
characters() —-文本元素事件
endElement() —-元素結束事件
endDocument() —-文檔結束事件
這裏寫圖片描述
XML文件同上

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<書架>
    <>
        <名稱>平凡的世界</名稱>
        <作者>路遙</作者>
        <售價>50</售價>
    </>

    <>
        <名稱>人生哲思錄</名稱>
        <作者>周國平</作者>
        <售價>2000</售價>
    </>
</書架>

JAVA代碼片,這邊只是使用了
characters() —-文本元素事件
endElement() —-元素結束事件
endDocument() —-文檔結束事件

package XML_Study.SAX_Study;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.junit.Test;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

public class SAX_study {
    /**
     * sax解析基礎操作,大多數都是用handle來進行,重寫defaultHandle類中的方法來進行,原因是使用ContentHandle重寫的方法太多了
     * 其他的東西都可以進行一系列的操作來進行
     * @throws Exception
     */
    @Test
    public void SAXParserTest1() throws Exception{
        SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
        SAXParser newSAXParser = saxParserFactory.newSAXParser();
        XMLReader reader=newSAXParser.getXMLReader();
        reader.setContentHandler(new DefaultHandler(){
            @Override
            public void startElement(String uri, String localName, String qName, Attributes attributes)//遇到開始元素所做的工作
                    throws SAXException {
                System.out.println("開始標籤"+qName);
            }
            @Override
            public void endElement(String uri, String localName, String qName) throws SAXException {//遇到結束元素所做的工作
                System.out.println("結束標籤"+qName);
            }
            @Override
            public void characters(char[] ch, int start, int length) throws SAXException {//遇到具體內容進行的操作
                System.out.println(new String(ch,start,length));
            }
        });
        reader.parse("src/XML_Study/SAX_Study/SAX_Study.xml");//開始解析
    }
}

3、PULL

  Pull解析器的運行方式與 SAX 解析器相似,都是輕量級的解析,在Android的內核中已經嵌入了Pull,所以我們不需要再添加第三方jar包來支持Pull。Android使用的就是pull進行解析所以pull顯得尤爲重要,但是pull和其他方式大同小異
  如果是編寫java代碼就需要導入第三方的jar包
  kxml2-2.3.0.jar和xmlpull_1_1_3_4c.jar版本沒有太大的關係
Pull解析和Sax解析不一樣的地方有:

  • pull讀取xml文件後觸發相應的事件調用方法返回的是數字
  • pull可以在程序中控制想解析到哪裏就可以停止解析。

方便參照將XML再貼一次

<?xml version="1.0" encoding="UTF-8" standalone="no"?><書架>
    <>
        <名稱>平凡的世界</名稱>
        <作者>路遙</作者>
        <售價>50</售價>
    </>

    <>
        <名稱>人生哲思錄</名稱>
        <作者>周國平</作者>
        <售價>2000</售價>
    </>
</書架>

在java代碼中使用了一個Book類,裏面只有Name,Author,Price三個變量以及對應的getter setter方法所以就不貼代碼了

package XML_Study.Pull_Study;

import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import org.junit.Test;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import com.sun.xml.internal.ws.api.pipe.NextAction;
import XML_Study.SAX_Study.Book;
public class PullParser_Study {
    public ArrayList<Book> booklist = new ArrayList();
    public boolean flag = false;
    public Book book = new Book();
/**
 * 使用了KXML 以及xmlpull包
 * @throws Exception
 */
    @Test
    public void Pull_Study() throws Exception {
        XmlPullParserFactory xmlPullParserFactory = XmlPullParserFactory.newInstance();
        XmlPullParser newPullParser = xmlPullParserFactory.newPullParser();// 獲取解析器
        newPullParser.setInput(new FileInputStream(new File("src/XML_Study/SAX_Study/SAX_Study.xml")), "UTF-8");// 第一個參數是輸入流,第二個參數是編碼格式
        int EvenType = newPullParser.getEventType();//使用一個常量進行保存,我們得到的元素的類型
        while (EvenType != XmlPullParser.END_DOCUMENT) {// 表示只要不是爲文件的末尾就可以了
            switch (EvenType) {
            case XmlPullParser.START_TAG://開始的元素
                if (newPullParser.getName().equals("書")) {
                    book = new Book();
                }
                if (newPullParser.getName().equals("名稱")) {
                    book.setName(newPullParser.nextText());//使用nextText()函數得到內容
                }
                if (newPullParser.getName().equals("作者")) {
                    book.setAuthor(newPullParser.nextText());
                }
                if (newPullParser.getName().equals("售價")) {
                    book.setPrice(newPullParser.nextText());
                }
            case XmlPullParser.END_TAG://表示結束的元素
                if (newPullParser.getName().equals("書架")) {
                for(Book book:booklist )
                    System.out.println(book.getName()+" "+book.getAuthor()+" "+book.getPrice());
                }if(newPullParser.getName().equals("書")){
                    booklist.add(book);
                }
            }
            EvenType=newPullParser.nextTag();//切忌加上此行代碼,防止出現死循環
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章