XML學習05-Java中SAX方式解析XML文件

一、什麼是SAX方式

-SAX: Simple API for XML。屬於開源社區XML-DEV,幾乎所有的XML解析器都支持它。
-相比於DOM方式,SAX方式更爲迅速,佔用內存資源更少。

二、Java中使用SAX方式解析XML的原理

-DOM方式與SAX方式的區別:DOM方式解析之前要將整個XML文檔讀入,在內存中產生一個DOM樹;而SAX方式解析是逐行掃描文檔,邊掃描邊進行解析,不必等到整個文檔裝載完才進行操作。
-Java中SAX解析XML的方式:SAX解析方式是基於事件驅動(一種基於回調(callback)機制的程序運行方法)的,利用SAX解析XML涉及解析器和事件處理器兩個部分。

a.解析器:對XML文檔逐行進行解析,只要解析到XML文檔的一個組成部分,都會去調用事件處理器的一個方法,解析器在調用事件處理器的方法時,會把當前解析到的XML文件內容作爲方法的參數傳遞給事件處理器。
b.事件處理器:由程序員編寫,決定對從解析器解析到的數據如何做處理。

-解析原理:
XML文檔——解析器逐行解析——>解析到元素——-調用相應的時間處理方法——>處理解析到的數據——-繼續解析下一行——>……

三、具體的Java代碼實現

1.創建解析器,處理器,加載XML文檔;2.內容處理的幾個主要方法;3.取出特定元素的內容;4.將XML中的信息全部輸出

待解析的XML代碼:

<?xml version="1.0" encoding="UTF-8" standalone="no"?><聯繫人列表>
    <聯繫人>
        <姓名>張三</姓名>
        <EMAIL>[email protected]</EMAIL>
        <年齡>30</年齡>
    </聯繫人>
    <聯繫人>
        <姓名>李四</姓名>
        <EMAIL>[email protected]</EMAIL>
        <年齡>31</年齡>
    </聯繫人>
</聯繫人列表>

1.創建解析器,處理器,加載XML文檔

//創建sax解析器
SAXParser sax = SAXParserFactory.newInstance().newSAXParser();
//獲取內容讀取器
XMLReader xml = sax.getXMLReader();
//註冊一個內容處理器
xml.setContentHandler(new DefaultHandler(){});//重寫DefaultHandler接口中的方法來處理解析到的內容
//加載XML文檔
xml.parse("src/j2ee/dom/linkman.xml");

2.內容處理用到的幾個主要方法(DefaultHandler 接口中)

i.startDocument() 
方法說明:在解析整個文檔開始時自動調用,重寫此方法可以在解析文檔開始時做特定處理。
ii.endDocument() 
方法說明:在解析整個文檔結束時自動調用,重寫此方法可以在解析整個文檔結束時做處理。
iii.startElement(String uri, String localName, String qName, Attributes attributes) 
參數說明:URL,本地名稱,當前解析到的元素名稱,元素附加的屬性
方法說明:在解析到元素節點時自動調用,重寫此方法可以在解析到元素節點時做相應處理。
iv.endElement(String uri, String localName, String qName) 
參數說明:URL,本地名稱,當前結束解析的元素名稱
方法說明:在解析到元素節點結束標籤時自動調用,重寫此方法可以在解析元素節點結束時做相應處理。
v.characters(char[] ch, int start, int length)
參數說明:XML文檔內容的字符數組,當前解析到的元素在字符數組的起始位置,當前解析到的元素所佔長度
方法說明:在解析完元素標籤方法結束後自動調用,重寫此方法可以對在此元素內讀取到的相應內容做處理。

解析時方法調用的流程:由startDocument開始,在endDocument結束,中間三個按順序反覆調用

startDocument()---->sartElement()---->characters()---->endElement()---->sartElement()---->characters()---->endElement()---->......--->endDocument()

3.取出特定元素的內容(取出XML中第二個聯繫人的姓名,運行結果輸出“李四”)

//創建sax解析器
SAXParser sax = SAXParserFactory.newInstance().newSAXParser();
//獲取內容讀取器
XMLReader xml = sax.getXMLReader();
//註冊一個內容處理器
xml.setContentHandler(new DefaultHandler(){
    String curname = "";//記錄當前的元素名
    int count = 0;//記錄當前取到的是第幾個聯繫人
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        if(qName.equals("姓名")){
            curname = "姓名";//只關注“姓名”元素
            count++;
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        curname="";//一個元素解析結束後應清空記錄的當前元素名
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        if("姓名".equals(curname)&&count==2){  //拿到了第二個聯繫人的姓名
            System.out.println(new String(ch,start,length));
        }
    }
});
//加載XML文檔
xml.parse("src/j2ee/dom/linkman.xml");

4.將XML中的信息全部輸出(定義一個linkman類封裝信息,此處忽略linkman類的代碼之關注主要代碼)

List<Linkman> men = new ArrayList<Linkman>();//定義一個容器來存放解析到的聯繫人對象
//創建sax解析器
SAXParser sax = SAXParserFactory.newInstance().newSAXParser();
//獲取內容讀取器
XMLReader xml = sax.getXMLReader();
//註冊一個內容處理器
xml.setContentHandler(new DefaultHandler(){

    Linkman man;//聯繫人對象
    String curname = "";//記錄當前解析的元素名
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        if(qName.equals("聯繫人")){
            man = new Linkman();//當解析到聯繫人元素時new一個新的聯繫人對象
        }
        curname = qName;
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if(qName.equals("聯繫人")){ //當一個聯繫人元素解析完成時,將這個聯繫人對象添加到容器中
            men.add(man);
        }
        curname="";
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        if("姓名".equals(curname)){ 
            man.setName(new String(ch,start,length));//若當前解析的是姓名元素,則將姓名的內容添加給聯繫人對象
        }
        if("EMAIL".equals(curname)){
            man.setEmail(new String(ch,start,length));//若當前解析的是EMAIL元素,則將Email內容添加給聯繫人對象
        }
        if("年齡".equals(curname)){
            man.setAge(Integer.parseInt(new String(ch,start,length)));//若當前解析的是年齡元素,則將年齡內容添加給聯繫人對象
        }
    }
});
//加載XML文檔
xml.parse("src/j2ee/dom/book.xml");


for (Linkman tmp: men ) {
    System.out.println(tmp.toString());
}

輸出結果如下:(成功將XML中全部信息解析)

張三--zhang3@gmail.com--30
李四--li4@163.com--31
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章