简析SAX解析xml文件

SAX解析
优点:不用实现调入整个文档,占用资源少。尤其在嵌入式环境中,如android,极力推荐使用SAX解析。
  缺点:不像DOM解析一样将文档长期驻留在内存中,数据不是持久的。如果事件过后没有保存数据,数据就会丢失。
  使用场合:机器有性能限制。
SAX(Simple API for XML)解析器是一种基于事件的解析器,事件驱动的流式解析方式是,从文件的开始顺序解析到文档的结束,不可暂停或倒退。它的核心是事件处理模式,主要是围绕着事件源以及事件处理器来工作的。当事件源产生事件后,调用事件处理器相应的处理方法,一个事件就可以得到处理。在事件源调用事件处理器中特定方法的时候,还要传递给事件处理器相应事件的状态信息,这样事件处理器才能够根据提供的事件信息来决定自己的行为。
SAX的工作原理:简单地说就是对文档进行顺序扫描,当扫描到文档(document)开始与结束、元素(element)开始与结束、文档(document)结束等地方时通知事件处理函数,由事件处理函数做相应动作,然后继续同样的扫描,直至文档结束
//设置一个可以定位文档内容事件发生位置的定位器对象
public void setDocumentLocator(Locator locator)
//用于处理文档解析开始事件
public void startDocument()throws SAXException
//处理元素开始事件,从参数中可以获得元素所在名称空间的uri,元素名称,属性类表等信息
public void startElement(String namespacesURI , String localName , String qName , Attributes atts) throws SAXException
//处理元素结束事件,从参数中可以获得元素所在名称空间的uri,元素名称等信息
public void endElement(String namespacesURI , String localName , String qName) throws SAXException
//处理元素的字符内容,从参数中可以获得内容
public void characters(char[] ch , int start , int length) throws SAXException
//注册处理XML文档解析事件ContentHandler
public void setContentHandler(ContentHandler handler)
//开始解析一个XML文档
public void parse(InputSorce input) throws SAXException

SAX实现实体解析的步骤:
在android中使用SAX是有迹可循的,完全可以按照下面的方法就可以轻松找到xml里的tag,然后得到想要的内容。具体实现步骤如下:
(一)第一步:新建一个工厂类SAXParserFactory,代码如下:
SAXParserFactory factory = SAXParserFactory.newInstance();
(二)第二步:让工厂类产生一个SAX的解析类SAXParser,代码如下:
SAXParser parser = factory.newSAXParser();
(三)第三步:从SAXPsrser中得到一个XMLReader实例,代码如下:
XMLReader reader = parser.getXMLReader();
(四)第四步:把自己写的handler注册到XMLReader中,一般最重要的就是ContentHandler,代码如下:
RSSHandler handler = new RSSHandler();
reader.setContentHandler(handler);
(五)第五步:将一个xml文档或者资源变成一个java可以处理的InputStream流后,解析正式开始,代码如下:

parser.parse(is);
上面几个步骤中,最重要、最关键的就是第四步,handler的实现。
rss.xml在project视图下的main里面加assets文件夹
在这里插入图片描述

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<beauties>
    <beauty>
        <name>范冰冰</name>
        <age>28</age>
    </beauty>
    <beauty>
        <name>杨幂</name>
        <age>23</age>
    </beauty>

</beauties>

Beauty.java

package com.example.mysax;

public class Bauty {
    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 + "]";
    }
}

RSSHandler.java

package com.example.mysax;



import java.util.ArrayList;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class RSSHandler extends DefaultHandler{

    //声明一个装载Beauty类型的List
    private ArrayList<Bauty> mList;
    //声明一个Beauty类型的变量
    private Bauty beauty;
    //声明一个字符串变量
    private String content;

    /**
     * RSSHandler的构造方法
     *
     * @param list 装载返回结果的List对象
     */
    public RSSHandler(ArrayList<Bauty> 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("beauty".equals(localName)){
            beauty = new Bauty(); //新建Beauty对象
        }
    }

    /**
     * 当SAX解析器解析到某个元素结束时,会调用的方法
     * 其中localName记录的是元素属性名
     */
    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        super.endElement(uri, localName, qName);

        if("name".equals(localName)){
            beauty.setName(content);
        }else if("age".equals(localName)){
            beauty.setAge(content);
        }else if("beauty".equals(localName)){
            mList.add(beauty); //将Beauty对象加入到List中
        }
    }
}

MainActivity.java

package com.example.mysax;


import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import android.app.Activity;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.widget.TextView;

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

import java.io.InputStream;
import java.util.ArrayList;

public class MainActivity extends Activity {
    private ArrayList<Bauty> beautyList;
    public TextView tv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //初始化beautyList链表
        if(beautyList == null){
            beautyList = new ArrayList<Bauty>();
        }

        doMyMission();

        setupViews();
    }

    /**
     * 使用SAX解析器解析XML文件的方法
     */
    private void doMyMission(){
        try {
            //获取AssetManager管理器对象
            AssetManager as = this.getAssets();
            //通过AssetManager的open方法获取到rss.xml文件的输入流
            InputStream is = as.open("rss.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传递给它,以便装载数据
            RSSHandler msh = new RSSHandler(beautyList);
            //将对象msh传递给xr
            xr.setContentHandler(msh);
            //调用xr的parse方法解析输入流
            xr.parse(is2);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 将解析结果输出到界面的方法
     */
    private void setupViews(){
        String result = "";

        for (Bauty b : beautyList) {
            result += b.toString();
        }

        tv = (TextView) findViewById(R.id.tv);
        tv.setText(result);
    }

}

**运行结果**

在这里插入图片描述

发布了8 篇原创文章 · 获赞 3 · 访问量 5172

猜你喜欢

转载自blog.csdn.net/s56564/article/details/104947353
今日推荐