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 主要就是用的解析的输入流列。

转载于:https://www.cnblogs.com/sunfb/p/3227183.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 中使用 SAX 解析 XML 文档时,如果 XML 文档包含特殊字符,需要进行转义处理,否则会导致 SAX 解析错误。和 DOM 解析不同,SAX 解析器会在解析到 XML 文档中的每个元素和属性时,调用相应的回调方法,因此需要在处理回调方法中进行转义处理。 以下是 Java 中常见的 XML 特殊字符及其转义方式: - 小于符号 (<):使用 "<" 表示; - 大于符号 (>):使用 ">" 表示; - 双引号 ("):使用 """ 表示; - 单引号 ('):使用 "&apos;" 表示; - 和符号 (&):使用 "&" 表示。 以处理 XML 元素值为例,可以在 DefaultHandler 的 characters() 方法中进行转义处理,示例如下: ```java import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class MyHandler extends DefaultHandler { private StringBuilder currentElementValue; @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { // 初始化当前元素值 currentElementValue = new StringBuilder(); } @Override public void characters(char[] ch, int start, int length) throws SAXException { // 将当前元素值加入 StringBuilder 中 currentElementValue.append(ch, start, length); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { // 处理当前元素值中的特殊字符 String elementValue = currentElementValue.toString() .replaceAll("&", "&") .replaceAll("<", "<") .replaceAll(">", ">") .replaceAll("\"", """) .replaceAll("'", "&apos;"); // 处理完特殊字符后,进行后续处理 // ... } } ``` 在上述示例中,使用 StringBuilder 来保存当前元素值,在 endElement() 方法中,先使用 toString() 方法将 StringBuilder 转化为字符串,然后使用 replaceAll() 方法将特殊字符转义为对应的实体。处理完特殊字符后,可以在 endElement() 方法中进行后续处理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值