JAVA-使用SAX解析XML資料
阿新 • • 發佈:2019-02-14
一、SAX (Simple API for XML)
- SAX解析XML檔案採用的是事件驅動,它不需要解析完整個文件,而是一邊按內容順序解析文件,一般判斷當前讀到的字元是否符合XML語法中的某部分,如果符合則會回撥一些函式來處理事件。
- 使用SAX的優點:SAX採用流的形式來處理,佔用記憶體少。
二、事件處理器DefaultHandler
事件驅動的回撥函式在DefaultHandler中,因此需要寫一個DefaultHandler子類,然後在回撥函式中處理相關的事件。
public class XMLPersonHandler extends DefaultHandler { @Override public void startDocument() throws SAXException { //開始解析xml之前的預處理 } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { // 解析到節點的開頭標籤'<...'時被呼叫 // uri:名稱空間 // localName:不帶名稱空間字首的標籤名 // qName:帶名稱空間的標籤名 // attributes:標籤的屬性集合 <person id="001"></person> // 如上,屬性id在attributes中,獲取標籤資料如下: // attributes.getQName( ),attributes.getValue( ) } @Override public void characters(char[] ch, int start, int length) throws SAXException { // 讀取**開頭標籤**到'>'時被呼叫,獲取標籤所夾的內容。 //<name>Jack</name> // ch[]:內容 // start:起始位置 // length:長度 //獲取內容:new String(ch,start,length); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { //解析到結束標籤時被呼叫 '/>' //<name>Jack</name> } @Override public void endDocument() throws SAXException { //文件解析結束時被呼叫 } }
三、解析器SAXParser
獲取解析器:
SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser sp = spf.newSAXParser();
解析XML資料:
//inputStream為讀取XML資料時的輸入流 XMLPersonHandler mhandler = new XMLPersonHandler(); sp.parse(inputStream, mhandler);
四、對DefaultHandler子類的封裝
XML中的資料獲取主要在自定義DefaultHandler子類中,所以可以在子類裡面進行資料的獲取和封裝。
對xml的結點資料內容獲取的簡單封裝:(不適合層次深的結點資料獲取)
public class XMLGeneralHandler extends DefaultHandler { private HashMap<String,String> map = null; private List<HashMap<String,String>> list = null; private String currentTag = null; private String currentValue = null; private String nodeName = null; public XMLGeneralHandler(String nodeName){ this.nodeName = nodeName; } public List<HashMap<String,String>> getList(){ return list; } @Override public void startDocument() throws SAXException { list = new ArrayList<>(); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if(qName.equals(nodeName)){ map = new HashMap<String,String>(); if(attributes!=null && map!=null){ for(int i=0;i<attributes.getLength();i++){ map.put(attributes.getQName(i), attributes.getValue(i)); } } } currentTag = qName; } @Override public void characters(char[] ch, int start, int length) throws SAXException { if(currentTag!=null && map!=null){ currentValue = new String(ch,start,length); if(currentValue!=null&&!currentValue.trim().equals("")&&!currentValue.trim().equals("\n")){ map.put(currentTag,currentValue); } } currentTag = null; currentValue = null; } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if(qName.equals(nodeName)){ list.add(map); map = null; } } @Override public void endDocument() throws SAXException { } }
對一些層次比較深的結點資料,可以自定義的通過結點資料的資訊來特定封裝。
五、程式碼測試:
獲取IT之家的新聞xml資料。
獲取xml資料的輸入流:
public class HttpUtil { public static InputStream getXML(String path){ InputStream inputStream = null; try{ URL url = new URL(path); if(url!=null){ HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setConnectTimeout(5000); connection.setDoInput(true); connection.setRequestMethod("GET"); int code = connection.getResponseCode(); if(code == 200){ inputStream = connection.getInputStream(); } } }catch(Exception e){ } return inputStream; } }
封裝的DefaultHandler子類:XMLGeneralHandler (如上)
測試類:
public class Test { public static void main(String[] args) { String path = "http://api.ithome.com/xml/newslist/news.xml"; System.out.println(path); InputStream inputStream = HttpUtil.getXML(path); try{ List<HashMap<String,String>> list = null; SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser sp = spf.newSAXParser(); XMLGeneralHandler mhandler = new XMLGeneralHandler("item"); sp.parse(inputStream, mhandler); inputStream.close(); list = mhandler.getList(); for(HashMap<String,String> p:list){ System.out.println(p.toString()); } }catch(Exception e){ } } }
列印輸出:
六、與PULL、DOM解析比較
- Dom解析xml,是先把全部資料讀入到記憶體中,然後檢索想要的資料,比較消耗記憶體,在xml文件比較小的情況下也可以考慮使用dom方式。
- android系統中,很多資原始檔都是xml格式,android系統解析這些xml的方式,是使用pul解析器進行解析的,也是採用事件驅動進行解析的。解析應用本地的xml可以採用pull解析。