JAVA-使用SAX解析XML数据

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

一、SAX (Simple API for XML)

  1. SAX解析XML文件采用的是事件驱动,它不需要解析完整个文档,而是一边按内容顺序解析文档,一般判断当前读到的字符是否符合XML语法中的某部分,如果符合则会回调一些函数来处理事件。
  2. 使用SAX的优点:SAX采用流的形式来处理,占用内存少。

二、事件处理器DefaultHandler

  1. 事件驱动的回调函数在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

  1. 获取解析器:

    SAXParserFactory spf = SAXParserFactory.newInstance();
    SAXParser sp =  spf.newSAXParser();
    
  2. 解析XML数据:

    //inputStream为读取XML数据时的输入流
    
    XMLPersonHandler mhandler = new XMLPersonHandler();
    sp.parse(inputStream, mhandler);
    

四、对DefaultHandler子类的封装

  1. XML中的数据获取主要在自定义DefaultHandler子类中,所以可以在子类里面进行数据的获取和封装。

  2. 对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 {
    
        }
    }
    
  3. 对一些层次比较深的结点数据,可以自定义的通过结点数据的信息来特定封装。

五、代码测试:

获取IT之家的新闻xml数据。

  1. 获取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;
        }
    
    }
    
  2. 封装的DefaultHandler子类:XMLGeneralHandler (如上)

  3. 测试类:

    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){
    
            }
    
    
        }
    
    }
    
  4. 打印输出:

六、与PULL、DOM解析比较

  1. Dom解析xml,是先把全部数据读入到内存中,然后检索想要的数据,比较消耗内存,在xml文档比较小的情况下也可以考虑使用dom方式。
  2. android系统中,很多资源文件都是xml格式,android系统解析这些xml的方式,是使用pul解析器进行解析的,也是采用事件驱动进行解析的。解析应用本地的xml可以采用pull解析。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值