Android SAX解析XML网络(一)

 SAX是一个解析速度快并且占用内存少的xml解析器,非常适合android等移动设备,SAX解析XML文件采用的是事件驱动,也就是说,它并不需要解析完整个文档,在按内容顺序解析文档的过程中,SAX会判断当前读取到的字符是否合法xml语法中的某部分,如果符合就会触发事件。事件驱动的流式解析方式是,从文件的开始顺序解析到文档的结束,不可暂停或倒退。它的核心是事件处理模式,主要是围绕着事件源以及事件处理器来工作的。当事件源产生事件后,调用事件处理器相应的处理方法,一个事件就可以得到处理。在事件源调用事件处理器中特定方法的时候,还要传递给事件处理器相应事件的状态信息,这样事件处理器才能够根据提供的事件信息来决定自己的行为。

SAX的工作原理:简单地说就是对文档进行顺序扫描,当扫描到文档(document)开始与结束、元素(element)开始与结束、文档(document)结束等地方时通知事件处理函数,由事件处理函数做相应动作,然后继续同样的扫描,直至文档结束。


第一种直接解析位于assets目录下的XML文件:

内容如下:

<?xml version="1.0" encoding="UTF-8"?>    
<persons>    
    <person>    
        <name>老马</name>    
        <age>30</age>    
    </person>    
    <person>    
        <name>小纳</name>    
        <age>23</age>    
    </person>    
    
</persons>   

创建一个与XML节点对应的person类:

package com.saxtest;  
  
public class Person {  
  
    private String name;  
    private String age;  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
  
    public String getAge() {  
        return age;  
    }  
  
    public void setAge(String age) {  
        this.age = age;  
    }  
  
    @Override  
    public String toString() {  
        return " [年龄=" + age + ", 姓名=" + name + "]";  
    }  
}  
接下来是比较重要的一个帮助类 MySaxHandler,在这个类中我们将解析出来的字符串生成了Person对象,并加入到List中,代码已经详细注释,内容如下:

package com.saxtest;  
  
import java.util.ArrayList;  
  
import org.xml.sax.Attributes;  
import org.xml.sax.SAXException;  
import org.xml.sax.helpers.DefaultHandler;  
  
public class MySaxHandler extends DefaultHandler{  
      
    //声明一个装载Person类型的List  
    private ArrayList<Person> mList;  
    //声明一个Person类型的变量  
    private Person person;  
    //声明一个字符串变量  
    private String content;  
      
    /** 
     * MySaxHandler的构造方法 
     *  
     * @param list 装载返回结果的List对象 
     */  
    public MySaxHandler(ArrayList<Person> list){  
        this.mList = list;  
    }  
      
    /** 
     * 当SAX解析器解析到XML文档开始时,会调用的方法 
     */  
    @Override  
    public void startDocument() throws SAXException {  
        super.startDocument();    
    }  
      
    /** 
     * 当SAX解析器解析到XML文档结束时,会调用的方法 
     */  
    @Override  
    public void endDocument() throws SAXException {  
        super.endDocument();  
    }  
      
    /** 
     * 当SAX解析器解析到某个属性值时,会调用的方法 
     * 其中参数ch记录了这个属性值的内容 
     */  
    @Override  
    public void characters(char[] ch, int start, int length)  
            throws SAXException {  
        super.characters(ch, start, length);  
        content = new String(ch, start, length);  
    }  
      
    /** 
     * 当SAX解析器解析到某个元素开始时,会调用的方法 
     * 其中localName记录的是元素属性名 
     */  
    @Override  
    public void startElement(String uri, String localName, String qName,  
            Attributes attributes) throws SAXException {  
        super.startElement(uri, localName, qName, attributes);  
  
        if("person".equals(localName)){  
            person = new Person(); //新建Person对象  
        }  
    }  
      
    /** 
     * 当SAX解析器解析到某个元素结束时,会调用的方法 
     * 其中localName记录的是元素属性名 
     */  
    @Override  
    public void endElement(String uri, String localName, String qName)  
            throws SAXException {  
        super.endElement(uri, localName, qName);  
          
        if("name".equals(localName)){  
            person.setName(content);  
        }else if("age".equals(localName)){  
            person.setAge(content);  
        }else if("person".equals(localName)){  
            mList.add(person); //将Person对象加入到List中  
        }  
    }  
}  

第三个源文件就是SaxTestActivity,现在我们贴出Activity源码的内容,代码都已经详细注释了:

package com.saxtest;  
  
import java.io.InputStream;  
import java.util.ArrayList;  
  
import javax.xml.parsers.SAXParser;  
import javax.xml.parsers.SAXParserFactory;  
  
import org.xml.sax.InputSource;  
import org.xml.sax.XMLReader;  
  
import android.app.Activity;  
import android.content.res.AssetManager;  
import android.os.Bundle;  
import android.widget.TextView;  
  
import com.example.saxtest.R;  
  
public class SaxTestActivity extends Activity{  
      
    //声明装载Person对象的List  
    private ArrayList<Person> beautyList;  
      
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.saxtest);  
          
        //初始化personList链表  
        if(personList == null){  
            personList = new ArrayList<Person>();  
        }  
          
        doMyMission();  
          
        setupViews();  
    }  
      
    /** 
     * 使用SAX解析器解析XML文件的方法 
     */  
    private void doMyMission(){  
        try {  
            //获取AssetManager管理器对象  
            AssetManager as = this.getAssets();  
            //通过AssetManager的open方法获取到persons.xml文件的输入流  
            InputStream is = as.open("persons.xml");  
            //通过获取到的InputStream来得到InputSource实例  
            InputSource is2 = new InputSource(is);  
            //使用工厂方法初始化SAXParserFactory变量spf  
            SAXParserFactory spf = SAXParserFactory.newInstance();  
            //通过SAXParserFactory得到SAXParser的实例  
            SAXParser sp = spf.newSAXParser();  
            //通过SAXParser得到XMLReader的实例  
            XMLReader xr = sp.getXMLReader();  
            //初始化自定义的类MySaxHandler的变量msh,将beautyList传递给它,以便装载数据  
            MySaxHandler msh = new MySaxHandler(personList);  
            //将对象msh传递给xr  
            xr.setContentHandler(msh);  
            //调用xr的parse方法解析输入流  
            xr.parse(is2);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
      
    /** 
     * 将解析结果输出到界面的方法 
     */  
    private void setupViews(){  
        String result = "";  
          
        for (Person b : personList) {    
            result += b.toString();    
        }    
  
        TextView textView = (TextView) findViewById(R.id.textView);    
        textView.setText(result);   
    }  
  
}  
布局文件比较简单,在此不贴出代码。

以上是对于assets目录下的XML文件的解析处理,但是更为普遍的是从网络上获取并解析。

从网上获取XML文件方法如下:

public class HttpDownloader  
{  
    private URL url = null;  
  
    /** 
     * 根据URL下载文件,前提是这个文件当中的内容是文本,函数的返回值就是文件当中的内容 
     * 1.创建一个URL对象 
     * 2.通过URL对象,创建一个HttpURLConnection对象 
     * 3.得到InputStram 
     * 4.从InputStream当中读取数据 
     * @param urlStr 
     * @return 
     */  
    public String download(String urlStr)  
    {  
        StringBuffer sb = new StringBuffer();  
        String line = null;  
        BufferedReader buffer = null;  
        try  
        {  
            // 创建一个URL对象  
            url = new URL(urlStr);  
            // 创建一个Http连接  
            HttpURLConnection urlConn = (HttpURLConnection) url  
                    .openConnection();  
            // 使用IO流读取数据  
            buffer = new BufferedReader(new InputStreamReader(urlConn  
                    .getInputStream()));  
            while ((line = buffer.readLine()) != null)  
            {  
                sb.append(line);  
            }  
        }  
        catch (Exception e)  
        {  
            e.printStackTrace();  
        }  
        finally  
        {  
            try  
            {  
                buffer.close();  
            }  
            catch (Exception e)  
            {  
                e.printStackTrace();  
            }  
        }  
        return sb.toString();  
    }  
  
    /** 
     * 该函数返回整形 -1:代表下载文件出错 0:代表下载文件成功 1:代表文件已经存在 
     */  
    public int downFile(String urlStr, String path, String fileName)  
    {  
        InputStream inputStream = null;  
        try  
        {  
            FileUtils fileUtils = new FileUtils();  
  
            if (fileUtils.isFileExist(path + fileName))  
            {  
                return 1;  
            }  
            else  
            {  
                inputStream = getInputStreamFromUrl(urlStr);  
                File resultFile = fileUtils.write2SDFromInput(path, fileName,  
                        inputStream);  
                if (resultFile == null)  
                {  
                    return -1;  
                }  
            }  
        }  
        catch (Exception e)  
        {  
            e.printStackTrace();  
            return -1;  
        }  
        finally  
        {  
            try  
            {  
                inputStream.close();  
            }  
            catch (Exception e)  
            {  
                e.printStackTrace();  
            }  
        }  
        return 0;  
    }  
  
    /** 
     * 根据URL得到输入流 
     *  
     * @param urlStr 
     * @return 
     * @throws MalformedURLException 
     * @throws IOException 
     */  
    public InputStream getInputStreamFromUrl(String urlStr)  
            throws MalformedURLException, IOException  
    {  
        url = new URL(urlStr);  
        HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();  
        InputStream inputStream = urlConn.getInputStream();  
        return inputStream;  
    }  
}  
则MainActivity里的代码如下:

HttpDownloader hd = new HttpDownloader();//new一个HttpDownloader对象  
            String resultStr = hd  
                    .download("http://192.168.1.112/test.xml");//把下载的字符串放在resultStr  
            try  
            {  
                /** 
                 * 创建一个SAXParserFactory,再用这个工厂来创建一个XMLReader,以此来读取XML 
                 * 这个方法就是这样写的,没有什么为什么,只是规定的格式罢了。 
                 */  
                SAXParserFactory factory = SAXParserFactory.newInstance();  
                XMLReader reader = factory.newSAXParser().getXMLReader();  
  
                //为XMLReader设置内容处理器,MyContentHandler()为具体处理的类  
                reader.setContentHandler(new MyContentHandler());  
                //开始解析文件  
                reader.parse(new InputSource(new StringReader(resultStr)));  
            }  
            catch (Exception e)  
            {  
                e.printStackTrace();  
            }  

以上学习内容来自:

android 用 SAX 解析xml文件!————boyupeng


Android之SAX解析XML——————bear_huangzhen





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值