zoukankan      html  css  js  c++  java
  • sax解析xml文件的DefaultHandler处理类

    一千年的时光,我无数次掀起岁月的帷幔,只为和你,在某一个平静如水的日子相遇,然后相识,倾情一生,缱绻一世,好美的散文,好吧,我情愿把这个“你”当作android;),使用sax解析xml文件是我见到过的最为简单的一种解析xml的方式了。java主要代码:

    SAXParserFactory factory = SAXParserFactory.newInstance();     
    SAXParser parser = factory.newSAXParser();     
    XMLReader xmlReader = parser.getXMLReader();     
    xmlReader.setContentHandler(mRSSHandler);     
    xmlReader.parse(new InputSource(mStream));

       这里要说明的是sax使用的工厂设计模式,通过SAXParserFactory 获取解析器parser ,在从解析器中获得解析xml文件的xmlReader
    ,但是在xmlReader
    读取流式的xml文件时,需要完成一个RSSHandler的设置,RSSHandler是继承的DefaultHandler,所以这篇文章着重详解使用sax解析xml文件的DefaultHandler处理类。这里我以解析网站的rss.xml文件为例,下面我们先看rss.xml的文件格式:

    xml/html代码:

    <?xml version="1.0" encoding="utf-8" ?>        
    <rss version="2.0">       
    <channel>       
    <item>       
    <title>Ubuntu11.04(10.04)安装dos工具dosemu</title>        
    <link>http://www.ourunix.org/post/276.html</link>        
    <author>ourunix@163.com (walfred)</author>        
    <category>玩转Linux</category>        
    <pubDate>Mon, 16 Jan 2012 22:54:53 +0800</pubDate>        
    <comments />        
    <description>看完介绍之后,发现这是继wine之后的有一款linux类win工具了,所以现在直接上文介绍dosemu在ubuntu Linux上的安装步骤及使用其运行dos游戏:魂斗罗~~~</description>        
    </item>       
    </channel>       
    </rss>  

     RSSHandler继承的DefaultHandler处理类就是专门来解析这个文件的,看下我们必须完成的接口:

    public void startDocument () {   
            //开始解析文档   
        }   
       
        public void endDocument () {   
            //文档解析结束   
        }   
       
        public void startElement (String uri, String localName, String qName, Attributes attributes) {   
            //开始解析节点   
        }   
           
        public void characters (char[] ch, int start, int length) {   
            //保存节点内容   
        }   
           
        public void endElement (String uri, String localName, String qName) {   
            //结束解析节点   
        }  

    一般前两个方法,开始解析和结束解析文档的不需要做处理外,我们的所有操作都是在解析节点部分,我们调用startElement
    开始解析节点,然后调用characters 保存节点的内容,最后调用endElement ,如此循环而已,可以看下解析rss的示例:

    public class RSSHandler extends DefaultHandler {   
        private Context mContext;   
        private RSSItem mRSSItem;   
        private RSSDBInterface mRSSDBInterface;   
           
        private final int TITLE_STATE = 1;   
        private final int AUTHOR_STATE = 2;   
        private final int LINK_STATE = 3;   
        private final int DESCRIPTION_STATE = 4;   
        private final int CATEGORY_STATE = 5;   
        private final int PUBDATE_STATE = 6;   
           
        //标记当前节点   
        private int currentState;   
           
        public RSSHandler(Context ctx){   
            mContext = ctx;   
            //初始化当前节点标记为0   
            currentState = 0;   
            //数据库接口   
            mRSSDBInterface = new RSSDBInterface(mContext);   
        }   
           
        public void startDocument () {   
            //开始解析文档   
            mRSSItem = new RSSItem(); 
        }   
       
        public void endDocument () {   
            //文档解析结束   
        }   
       
        public void startElement (String uri, String localName, String qName, Attributes attributes) {   
            //开始解析节点   
            if (localName.equals("channel")){   
                return ;   
            }   
               
    
            if (localName.equals("item")){   
                //当遇到一个item节点时,就实例化一个RSSItem对象   
                mRSSItem = new RSSItem();   
                return;   
            }   
               
            if (localName.equals("title")){   
                currentState = TITLE_STATE;   
                return ;   
            }   
               
            if (localName.equals("author")){   
                currentState = AUTHOR_STATE;   
                return ;   
            }   
               
            if (localName.equals("description")){   
                currentState = DESCRIPTION_STATE;   
                return ;   
            }   
               
            if (localName.equals("link")){   
                currentState = LINK_STATE;   
                return ;   
            }   
               
            if (localName.equals("category")){   
                currentState = CATEGORY_STATE;   
                return ;   
            }   
               
            if (localName.equals("pubDate")){   
                currentState = PUBDATE_STATE;   
                return ;   
            }   
        }   
           
        public void endElement (String uri, String localName, String qName) {   
            //这是节点解析完成时调用的,这里我们遇到item的时候才调用下面的   
            if(localName.equals("item" && mRSSItem != null)){   
                ContentValues values = new ContentValues();   
                values.put(RSSDBInfo.Columns._TITLE, mRSSItem.getTitle());   
                values.put(RSSDBInfo.Columns._AUTHOR, mRSSItem.getAuthor());   
                values.put(RSSDBInfo.Columns._CATEGORY, mRSSItem.getCategory());   
                values.put(RSSDBInfo.Columns._DESCRIPTION, mRSSItem.getDescription());   
                values.put(RSSDBInfo.Columns._LINK, mRSSItem.getLink());   
                values.put(RSSDBInfo.Columns._PUBDATE, mRSSItem.getPubdate());   
                values.put(RSSDBInfo.Columns._ISREAD, RSSUtils.ARTICALE_UNREAD);   
                mRSSDBInterface.insertRSStoDB(values);   
            }   
        }   
           
        public void characters (char[] ch, int start, int length) {   
            String theString = new String(ch, start, length);   
            switch(currentState){   
            case TITLE_STATE:   
                mRSSItem.setTitle(theString);   
                currentState = 0;   
                break;   
                   
            case AUTHOR_STATE:   
                mRSSItem.setAuthor(theString);   
                currentState = 0;   
                break;   
                   
            case LINK_STATE:   
                mRSSItem.setLink(theString);   
                currentState = 0;   
                break;   
                   
            case DESCRIPTION_STATE:   
                mRSSItem.setDescription(theString);   
                currentState = 0;   
                break;   
                   
            case CATEGORY_STATE:   
                mRSSItem.setCategory(theString);   
                currentState = 0;   
                break;   
                   
            case PUBDATE_STATE:   
                mRSSItem.setPubdate(theString);   
                currentState = 0;   
                break;   
            }   
        }   
    }  

      这就SAX的工厂模式的解析。

    注释:ContentValues 是类似Map一样的类,存储键值的。

       InputSource 主要就是用的解析的输入流列。

  • 相关阅读:
    XSS练习小游戏和答案参考
    nxlog以syslog方式发送日志
    Hydra—密码爆破神器
    syslog服务器配置笔记
    信息安全工具汇总整理
    nmap使用指南
    Cleaner, more elegant, and harder to recognize (msdn blog)
    Golang 中的坑 一
    Concurrency Is Not Parallelism (Rob pike)
    golang sql database drivers
  • 原文地址:https://www.cnblogs.com/sunfb/p/3227183.html
Copyright © 2011-2022 走看看