一、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解析。
本文详细介绍了使用SAX解析XML数据的方法,包括SAX解析的事件驱动原理、DefaultHandler事件处理器的实现、SAXParser的使用,以及如何封装DefaultHandler子类来处理XML数据。通过代码测试展示了如何获取并解析XML数据,最后对比了SAX与DOM、PULL解析器的优缺点。
684

被折叠的 条评论
为什么被折叠?



