JAVA-使用SAX解析XML資料
一、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解析。
相關文章
- java使用sax解析xmlJavaXML
- python使用SAX解析xmlPythonXML
- XML解析-最快的方式SAXXML
- Android系列--DOM、SAX、Pull解析XMLAndroidXML
- python 解析xml 檔案: SAX方式PythonXML
- Python解析xml大檔案(sax)PythonXML
- XML解析的兩種方式DOM和SAXXML
- Sax 解析xml檔案時, 資料資訊不完整問題解決方法XML
- 關於SAX解析xml檔案的問題XML
- 用Java結合SAX 2.0 解析XML文件 (轉)JavaXML
- SAX無法正確解析日期資料
- XML資料解析XML
- 使用JAXP進行DOM解析_SAX解析
- :Android網路程式設計--XML之解析方式:SAXAndroid程式設計XML
- Java解析XML彙總(DOM/SAX/JDOM/DOM4j/XPath)JavaXML
- DOM解析和SAX解析
- SAX處理XML例項XML
- POI 使用SAX讀取大資料Excel大資料Excel
- sax解析例子演示
- jaxp的sax解析操作
- [轉]使用 SAX 處理 XML 文件 和與DOM的區別XML
- 使用jdom解析XMLXML
- Dom4j解析XML資料XML
- dom解析和sax解析的區別
- SAX解析XML檔案有關characters的最大長度2048的問題XML
- NPM酷庫051:xml2js,解析XML格式資料NPMXMLJS
- Android 中 XML 資料解析詳解AndroidXML
- iOS開發之解析XML格式資料iOSXML
- org.xml.sax.SAXParseException: XML 宣告可能只能從實體開始。XMLException
- 使用DocumentBuilderFactory解析XML淺談UIXML
- 使用 Java 解析XML檔案JavaXML
- 使用JAXP進行SAX解析(XMLReaderFactory、XMLReader 、SAXParserFactory與SAXParser)XML
- Java-進階篇【Junit單元測試、反射、註解、動態代理、XML、XML解析、XPath、設計模式】---10Java反射XML設計模式
- XML的四種解析器(dom_sax_jdom_dom4j)原理及效能比較[收藏]XML
- Java-常見資料結構Java資料結構
- xml問題請教:org.xml.sax.SAXParseException: Invalid encoding name "GBK".XMLExceptionEncoding
- JBoss報錯,org.xml.sax.SAXParseException?老大幫我看看XMLException
- Xml解析XML