快速解析XML

  SAX解析XML文件採用事件驅動的方式進行,也就是說,SAX是逐行掃描文件,遇到符合條件的設定條件後就會觸發特定的事件,回調你寫好的事件處理程序。使用SAX的優點在於其解析速度較快,相對於DOM而言佔用內存較少。並且SAX在解析文件的過程當中獲得本身須要的信息後能夠隨時終止解析,並不必定要等文件所有解析完畢。凡事有利必有弊,其劣勢在於SAX採用的是流式處理方式,當遇到某個標籤的時候,它並不會記錄下之前所遇到的標籤,也就是說,在處理某個標籤的時候,好比在startElement方法中,所可以獲得的信息就是標籤的名字屬性,至於標籤內部的嵌套結構,上層標籤、下層標籤以及其兄弟節點的名稱等等與其結構相關的信息都是不得而知的。實際上就是把XML文件的結構信息丟掉了,若是須要獲得這些信息的話,只能你本身在程序裏進行處理了。因此相對DOM而言,SAX處理XML文檔沒有DOM方便,SAX處理的過程相對DOM而言也比較複雜。html

        SAX採用事件處理的方式解析XML文件,利用 SAX 解析 XML 文檔,涉及兩個部分:解析器和事件處理器:
解析器可使用JAXP的API建立,建立出SAX解析器後,就能夠指定解析器去解析某個XML文檔。
解析器採用SAX方式在解析某個XML文檔時,它只要解析到XML文檔的一個組成部分,都會去調用事件處理器的一個方法,解析器在調用事件處理器的方法時,會把當前解析到的xml文件內容做爲方法的參數傳遞給事件處理器。
事件處理器由程序員編寫,程序員經過事件處理器中方法的參數,就能夠很輕鬆地獲得sax解析器解析到的數據,從而能夠決定如何對數據進行處理。java

備註說明:SAX API中主要有四種處理事件的接口,它們分別是ContentHandlerDTDHandler, EntityResolver 和 ErrorHandler 程序員

 這裏使用最多的就是ContentHandler,仔細閱讀 API文檔,瞭解經常使用方法:startElement、endElement、characters等web

 1.startElement方法說明api

[java]數組

  1. void startElement(String uri,  
                      String localName,  
                      String qName,  
                      Attributes atts)  
                      throws SAXException  
    方法說明:  
    解析器在 XML 文檔中的每一個元素的開始調用此方法;對於每一個 startElement 事件都將有相應的 endElement 事件(即便該元素爲空時)。全部元素的內容都將在相應的 endElement 事件以前順序地報告。  
      
    參數說明:  
    uri - 名稱空間 URI,若是元素沒有名稱空間 URI,或者未執行名稱空間處理,則爲空字符串  
    localName - 本地名稱(不帶前綴),若是未執行名稱空間處理,則爲空字符串  
    qName - 限定名(帶有前綴),若是限定名不可用,則爲空字符串 (標籤名) 
    atts - 鏈接到元素上的屬性。若是沒有屬性,則它將是空 Attributes 對象。在 startElement 返回後,此對象的值是未定義的(標籤名屬性)

 2.endElement方法說明app

[java]ide

  1.  

  2. void endElement(String uri,  
                    String localName,  
                    String qName)  
                    throws SAXException接收元素結束的通知。   
    SAX 解析器會在 XML 文檔中每一個元素的末尾調用此方法;對於每一個 endElement 事件都將有相應的 startElement 事件(即便該元素爲空時)。  
      
    參數:  
    uri - 名稱空間 URI,若是元素沒有名稱空間 URI,或者未執行名稱空間處理,則爲空字符串  
    localName - 本地名稱(不帶前綴),若是未執行名稱空間處理,則爲空字符串  
    qName - 限定的 XML 名稱(帶前綴),若是限定名不可用,則爲空字符串


3.characters方法測試

[java] spa

  1. void characters(char[] ch,  
                    int start,  
                    int length)  
                    throws SAXException  
    接收字符數據的通知,能夠經過new String(ch,start,length)構造器,建立解析出來的字符串文本.  
    參數:  
    ch - 來自 XML 文檔的字符  
    start - 數組中的開始位置  
    length - 從數組中讀取的字符的個數


說明:xml中每一個標籤的文本內容是在characters方法裏處理的。

好比在以下:

  1. <?xml version="1.0" encoding="UTF-8"?>  
    <!DOCTYPE 四大名著[  
    <!ELEMENT 四大名著 (西遊記,紅樓夢)>  
    <!ATTLIST 西遊記 id ID #IMPLIED>  
    ]>  
    <四大名著>  
        <西遊記 id="x001">  
            <做者>吳承恩</做者>  
        </西遊記>  
        <紅樓夢 id="x002">  
            <做者>曹雪芹</做者>  
        </紅樓夢>  
    </四大名著>

在<西遊記 id="x001"><做者>吳承恩</做者></西遊記>裏

吳承恩這個文本就是在characters方法裏處理的。

其中<西遊記></西遊記>和<做者></做者>是標籤(qname)

id="x001"是屬性(atts)和值

其它方法請參考api數據



下面咱們就具體講解sax解析的操做.

一.咱們經過XMLReaderFactory、XMLReader完成,步驟以下

[java]

  1. 1.經過XMLReaderFactory建立XMLReader對象  
    XMLReader reader = XMLReaderFactory.createXMLReader();  
    2. 設置事件處理器對象  
    reader.setContentHandler(new MyDefaultHandler());  
    3.讀取要解析的xml文件  
    FileReader fileReader =new FileReader(new File("src\\sax\\startelement\\web.xml"));  
    4.指定解析的xml文件  
    reader.parse(new InputSource(fileReader));


案例:經過案例對uri、localName、qName和attribute參數有更加深刻的瞭解

1.首先建立要解析的web.xml文件,內容以下

[html]

  1. <?xml version="1.0" encoding="UTF-8"?>  
    <web-app version="2.5"   
        xmlns:csdn="http://java.sun.com/xml/ns/javaee"   
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   
        http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">  
      <csdn:display-name></csdn:display-name>     
    </web-app>  
    <!--   
    uri - 名稱空間 URI,若是元素沒有任何名稱空間 URI,或者沒有正在執行名稱空間處理,則爲空字符串。  
    xml namespace-xmlns  
    localName - 本地名稱(不帶前綴),若是沒有正在執行名稱空間處理,則爲空字符串。  
    qName - 限定的名稱(帶有前綴),若是限定的名稱不可用,則爲空字符串。  
    attributes - 附加到元素的屬性。若是沒有屬性,則它將是空的 Attributes 對象。   
     -->


2.建立解析測試類及事件處理的內部類代碼以下

[java]

  1. package sax.startelement;  
      
    import java.io.File;  
    import java.io.FileReader;  
      
    import org.junit.Test;  
    import org.xml.sax.Attributes;  
    import org.xml.sax.InputSource;  
    import org.xml.sax.SAXException;  
    import org.xml.sax.XMLReader;  
    import org.xml.sax.helpers.DefaultHandler;  
    import org.xml.sax.helpers.XMLReaderFactory;  
      
    public class Demo3 {  
      
        @Test  
        public void test() throws Exception {  
            // 經過XMLReaderFactory建立XMLReader對象  
            XMLReader reader = XMLReaderFactory.createXMLReader();  
            // 設置事件處理器對象  
            reader.setContentHandler(new MyDefaultHandler());  
            // 讀取要解析的xml文件  
            FileReader fileReader = new FileReader(new File(  
                    "src\\sax\\startelement\\web.xml"));  
            // 指定解析的xml文件  
            reader.parse(new InputSource(fileReader));  
        }  
      
        // 自定義的解析類,經過此類中的startElement瞭解uri,localName,qName,Attributes的含義  
        class MyDefaultHandler extends DefaultHandler {  
      
            @Override  
            public void startElement(String uri, String localName, String qName,  
                    Attributes attributes) throws SAXException {  
                super.startElement(uri, localName, qName, attributes);  
                System.out  
                        .println("--------------startElement開始執行--------------------------");  
                System.out.println("uri:::" + uri);  
                System.out.println("localName:::" + localName);  
                System.out.println("qName:::" + qName);  
                for (int i = 0; i < attributes.getLength(); i++) {  
                    String value = attributes.getValue(i);// 獲取屬性的value值  
                    System.out.println(attributes.getQName(i) + "-----" + value);  
                }  
                System.out.println("------------------startElement執行完畢---------------------------");  
            }  
      
        }  
    }


3.程序運行的結果以下:


經過運行結果,但願你對uri,localName,qName有更加深刻的瞭解.


二.咱們經過SAXParserFactory、SAXParser完成,步驟以下(建議使用)

說明:若是隻是使用SAXParserFactory、SAXParser他們完成只須要以下3步驟

1.獲取sax解析器的工廠對象
SAXParserFactory factory = SAXParserFactory.newInstance();
2.經過工廠對象 SAXParser建立解析器對象
SAXParser saxParser = factory.newSAXParser();
3.經過解析saxParser的parse()方法設定解析的文件和本身定義的事件處理器對象
saxParser.parse(new File("src//sax//sida.xml"), new MyDefaultHandler());

案例:解析出"做者"元素標籤中的文本內容

1.須要解析的sida.xml文件

[html]

  1. <?xml version="1.0" encoding="UTF-8"?>  
    <!DOCTYPE 四大名著[  
    <!ELEMENT 四大名著 (西遊記,紅樓夢)>  
    <!ATTLIST 西遊記 id ID #IMPLIED>  
    ]>  
    <四大名著>  
        <西遊記 id="x001">  
            <做者>吳承恩</做者>  
        </西遊記>  
        <紅樓夢 id="x002">  
            <做者>曹雪芹</做者>  
        </紅樓夢>  
    </四大名著>


2.解析測試類和事件處理器類的實現代碼

[java] 

  1. package sax;  
      
    import java.io.File;  
      
    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.helpers.DefaultHandler;  
      
    public class SaxTest {  
      
        @Test  
        public void test() throws Exception {  
            // 1.獲取sax解析器的工廠對象  
            SAXParserFactory factory = SAXParserFactory.newInstance();  
            // 2.經過工廠對象 SAXParser建立解析器對象  
            SAXParser saxParser = factory.newSAXParser();  
            // 3.經過解析saxParser的parse()方法設定解析的文件和本身定義的事件處理器對象  
            saxParser.parse(new File("src//sax//sida.xml"), new MyDefaultHandler());  
      
        }  
      
        // 本身定義的事件處理器  
        class MyDefaultHandler extends DefaultHandler {  
      
            // 解析標籤開始及結束的的標識符  
            boolean isOk = false;  
      
            @Override  
            public void startElement(String uri, String localName, String qName,  
                    Attributes attributes) throws SAXException {  
                super.startElement(uri, localName, qName, attributes);  
                // 當解析做者元素開始的時候,設置isOK爲true  
                if ("做者".equals(qName)) {  
                    isOk = true;  
                }  
            }  
      
            @Override  
            public void characters(char[] ch, int start, int length)  
                    throws SAXException {  
                // TODO Auto-generated method stub  
                super.characters(ch, start, length);  
                // 當解析的標識符爲true時,打印元素的內容  
                if (isOk) {  
                    System.out.println(new String(ch, start, length));  
                }  
            }  
              
            @Override  
            public void endElement(String uri, String localName, String qName)  
                    throws SAXException {  
                super.endElement(uri, localName, qName);  
                // 當解析做者元素的結束的時候,設置isOK爲false  
                if ("做者".equals(qName)) {  
                    isOk = false;  
                }  
            }  
      
        }  
    }


3.程序運行結果以下:



原文地址:http://blog.csdn.net/redarmy_chen/article/details/12951649

相關文章
相關標籤/搜索