Android 中的XML 解析方法Pull 和Sax

代码:Pull和SAX 解析的实例

XML 解析一般有三种,DOM,Pull和SAX,相比于DOM的,Pull 和SAX内存占用小效率高,所以我们一般使用Pull和SAX解析。
0:Pull和SAX都是通过工厂类来创建解析类的.
1:Pull和SAX的最大的区别就是,具体的解析的过程,SAX 是在while 循环里面通过XmlPullParser.next()来遍历的,而Pull 是通过专门的DefaultHanlder 来处理的,结构上面SAX更好,


Pull流程:
0:首先通过工厂类来获取XmlPullParser的实体类,
1:得到xml的文件的输入流,这个输入流可以是通过网络得到的也可以是通过本地得到的,例如放在raw文件夹里面的文件
2:通过setInput 来开始读取,还需要设置它的编码

//XmlPullParser的工厂类
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser = factory.newPullParser();
//xmlPullParser.setInput的第一个参数就是 InputStream//这里是将xml 文件放在了raw文件夹里面,然后通过getResources().openRawResource(R.raw.worker)来获取
InputStream inputStream = getResources().openRawResource(R.raw.worker);
//开始读取文件,并设置编码类型为utf-8
xmlPullParser.setInput(inputStream, "utf-8");

3:读取的时候是通过eventType来判断当前的位置是文件的开始开始还是结束,还是节点的开始和节点的结束.通过XmlPullParser的next的方法来跳到下一个节点。

//获取event的类型,然后循环直至END_DOCUMENT,循环的增加条件一定不能忘记eventType=xmlPullParser.next();
int eventType = xmlPullParser.getEventType();
while (eventType!=XmlPullParser.END_DOCUMENT){
.....
   eventType=xmlPullParser.next();
}
4:在节点的START_TAG里面通过XmlPullParser的nextText()来获取节点里面的内容,
5:如果这个节点里面有属性,可以通过XmlPullParser的getAttributeCount来获取属性的总数,然后循环获取,通过getAttributeName getAttributeValue 来获取属性名字和值



SAX流程:

0:首先也是通过工厂类来获取SAXParser的实体类
1:然后获取XMLReader
2:创建MyHandler,
处理类DefaultHandler 里面的5个方法和我们Pull里面的while 循环里面相对应的。结构更明显。
startDocument() 
startElement(String uri, String localName, String qName, Attributes attributes)
characters(char[] ch, int start, int length)
endElement(String uri, String localName, String qName)
endDocument()


记住了在endElement 里面一定要设置全局变量mQualifiedName=null,因为在xml文件里面,它会将TAB的符号也读入进来,不仅仅是节点信息,
当读完了endElement 以后,它继续读取后面的内容,例如下面的name 的节点后面就有换行符号,下一行读取到sex 之前还有两个Tab的符号。所以读取的Tab 信息会覆盖原来的Mark的这个信息
<workers>
<worker id="AQ01">
<name>Mark</name>
<sex>男</sex>
<status>经理</status>
<address>北京</address>
<money>4000</money>
</worker>


3:将MyHandler设置到xmlReader
xmlReader.setContentHandler(saxHandler);
4:然后开始读取
xmlReader.parse(new InputSource(getResources().openRawResource(R.raw.worker)));
5:最后获取List
        saxList = saxHandler.getmList();


//SAX 的工厂类
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
SAXParser saxParser = saxParserFactory.newSAXParser();
// 通过parser得到XMLReader对象
XMLReader xmlReader = saxParser.getXMLReader();
//创建MyHandler的实例
MyHandler saxHandler = new MyHandler();
//saxHanlder 放入xmlReader中。
xmlReader.setContentHandler(saxHandler);
xmlReader.parse(new InputSource(getResources().openRawResource(R.raw.worker)));
//此时通过MyHandler 里面的方法来获取List<Worker>
saxList = saxHandler.getmList();


具体实例如下:

++++++++++++++++++++++++++++++++++++++++++++++

XML 文件:

<?xml version="1.0" encoding="UTF-8"?>
<workers>
   <worker id="AQ01">
      <name>Mark</name>
      <sex></sex>
      <status>经理</status>
      <address>北京</address>
      <money>4000</money>
   </worker>
   <worker id="AD02">
      <name>Luch</name>
      <sex></sex>
      <status>员工</status>
      <address>上海</address>
      <money>1000</money>
   </worker>
   <worker id="AD03">
      <name>Lily</name>
      <sex></sex>
      <status>员工</status>
      <address>北京</address>
      <money>2000</money>
   </worker>
   <worker>
      <name>Lily</name>
      <sex></sex>
      <status>员工</status>
      <address>北京</address>
      <money>2000</money>
   </worker>
</workers>


+++++++++++++++++++++++++++++++++++++++++++++++++++

Worker实体类

package tech.androidstudio.xmlpullparserdemo;

/**
 * Created by Kodulf on 2016/3/18.
 */
public class Worker {

    private String id;
    private String name;
    private String sex;
    private String status;
    private String address;

    public Worker() {
    }

    public Worker(String id, String name, String sex, String status, String address, double money) {

        this.id = id;
        this.name = name;
        this.sex = sex;
        this.status = status;
        this.address = address;
        this.money = money;
    }

    @Override
    public String toString() {
        return "Worker{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", status='" + status + '\'' +
                ", address='" + address + '\'' +
                ", money=" + money +
                '}';
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    private double money;

}


++++++++++++++++++++++++++++++++++++++++++++++++++++++

MainActivity
++++++++++++++++++++++++++++++++++++++++
package tech.androidstudio.xmlpullparserdemo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

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

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        List<Worker> list = null;
        try {
            list = pullGetList();
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //输出结果
        Log.d("kodulf", list.toString());


        try {
            list=saxGetList();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //输出结果
        Log.d("kodulf","SAX 解析的结果"+list.toString());
    }

    private List<Worker> pullGetList() throws XmlPullParserException, IOException {
        /**
        <worker id="AQ01">
        <name>Mark</name>
        <sex></sex>
        <status>经理</status>
        <address>北京</address>
        <money>4000</money>
        </worker>
         */

        List<Worker> list = new ArrayList<Worker>();
        Worker worker=null;
        //XmlPullParser的工厂类
        XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
        XmlPullParser xmlPullParser = factory.newPullParser();

        //xmlPullParser.setInput的第一个参数就是 InputStream        //这里是将xml 文件放在了raw文件夹里面,然后通过getResources().openRawResource(R.raw.worker)来获取
        InputStream inputStream = getResources().openRawResource(R.raw.worker);
        //开始读取文件,并设置编码类型为utf-8
        xmlPullParser.setInput(inputStream, "utf-8");

        //获取event的类型,然后循环直至END_DOCUMENT,循环的增加条件一定不能忘记eventType=xmlPullParser.next();
        int eventType = xmlPullParser.getEventType();
        while (eventType!=XmlPullParser.END_DOCUMENT){
            switch (eventType){
                case XmlPullParser.START_DOCUMENT:
                    Log.d("Kodulf","start document");
                    break;
                //每一个节点开始标签,开始判断,判断是哪一个节点
                case XmlPullParser.START_TAG:
                    //获取节点名字就像是namesexstatusaddressmoney
                    String name = xmlPullParser.getName();
                    //<worker id="AQ01"> 第一个 节点,里面有一个id的属性,通过getAttribute来获取
                    if("worker".equals(name)){
                        worker = new Worker();
                        int attributeCount = xmlPullParser.getAttributeCount();
                        for (int i = 0; i < attributeCount; i++) {
                            String attributeName = xmlPullParser.getAttributeName(i);
                            if("id".equals(attributeName)){
                                String attributeValue = xmlPullParser.getAttributeValue(i);
                                worker.setId(attributeValue);
                            }
                        }
                        //节点name,获取里面的内容是通过xmlPullParser.nextText()来获取的。
                    }else if("name".equals(name)){
                        String text = xmlPullParser.nextText();
                        worker.setName(text);
                    }else if("sex".equals(name)){
                        String text = xmlPullParser.nextText();
                        worker.setSex(text);
                    }else if("status".equals(name)){
                        String text = xmlPullParser.nextText();
                        worker.setStatus(text);
                    }else if("address".equals(name)){
                        String text = xmlPullParser.nextText();
                        worker.setAddress(text);
                        //节点money的内容也是通过xmlPullParser.nextText()来获取,
                        // 但是设置的时候因为我们的实体类是double类型的所以要转换一下
                    }else if("money".equals(name)){
                        String text = xmlPullParser.nextText();
                        worker.setMoney(Double.parseDouble(text));
                    }
                    break;
                // END_TAG里面判断最后的节点,然后添加到list里面去
                case XmlPullParser.END_TAG:
                    String name1 = xmlPullParser.getName();
                    if ("worker".equals(name1)){
                        list.add(worker);
                    }
                    break;
            }
            //TODO 这个判断条件一定不能变
           eventType=xmlPullParser.next();
        }

        return list;
    }


    //SAX 解析
    public List<Worker> saxGetList() throws ParserConfigurationException, SAXException, IOException {
        List<Worker> saxList = new ArrayList<Worker>();
        //SAX 的工厂类
        SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
        SAXParser saxParser = saxParserFactory.newSAXParser();
        // 通过parser得到XMLReader对象
        XMLReader xmlReader = saxParser.getXMLReader();
        //创建MyHandler的实例
        MyHandler saxHandler = new MyHandler();
        //saxHanlder 放入xmlReader中。
        xmlReader.setContentHandler(saxHandler);
        xmlReader.parse(new InputSource(getResources().openRawResource(R.raw.worker)));
        //此时通过MyHandler 里面的方法来获取List<Worker>
        saxList = saxHandler.getmList();


        return saxList;
    }

}
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

SAX的DefaultHandler

package tech.androidstudio.xmlpullparserdemo;

import android.util.Log;

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

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Kodulf on 2016/3/18.
 */
public class MyHandler extends DefaultHandler {
    List<Worker> mList;
    Worker mWorker;
    String mQualifiedName;
    /**
     <worker id="AQ01">
     <name>Mark</name>
     <sex></sex>
     <status>经理</status>
     <address>北京</address>
     <money>4000</money>
     </worker>
     */
    @Override
    public void startDocument() throws SAXException {
        super.startDocument();
        Log.d("Kodulf", "SAX start Document");
        // startDocument 里面初始化List
        mList = new ArrayList<Worker>();
    }

    //这里的 qName-qualified name 限定名 ,这个 参数要设置为成员变量,因为下面的characters里面需要用到。
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        super.startElement(uri, localName, qName, attributes);
        mQualifiedName=qName;
        //如果startElementworker的话,<worker id="AQ01">,要获取属性id的 值
        if("worker".equals(qName)){
            mWorker = new Worker();
            int length = attributes.getLength();
            for (int i = 0; i < length; i++) {
                String attributeName = attributes.getQName(i);
                if("id".equals(attributeName)){
                    String attributeValue = attributes.getValue(i);
                    mWorker.setId(attributeValue);
                }
            }
        }
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        /**
        <name>Mark</name>
        <sex></sex>
        <status>经理</status>
        <address>北京</address>
        <money>4000</money>
                */
        super.characters(ch, start, length);
        String nodeValue = new String(ch,start,length);
        if("name".equals(mQualifiedName)){
            mWorker.setName(nodeValue);
        }else if("sex".equals(mQualifiedName)){
            mWorker.setSex(nodeValue);
        }else if("status".equals(mQualifiedName)){
            mWorker.setStatus(nodeValue);
        }else if("address".equals(mQualifiedName)){
            mWorker.setAddress(nodeValue);
        }else if("money".equals(mQualifiedName)){
            //注意这里的Money double 类型的,所以要转换一下
            mWorker.setMoney(Double.parseDouble(nodeValue));
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        super.endElement(uri, localName, qName);
        //TODO 一定要将全局变量mQualifiedName 设置为空,
        //例如下面的</money>的节点后面就有换行符号,下一行读取到</worker>之前还有Tab的符号。
        // 所以读取的Tab 信息会覆盖原来的4000的这个信息.所以再赋值的时候 就是将一个Tab的信息复制给Double 的了,所以报错了。
        mQualifiedName=null;
        //判断是否是worker,如果是的话,就将mWorker 添加到list 里面去
        if("worker".equals(qName)){
            mList.add(mWorker);
        }
    }

    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
        Log.d("Kodulf", "SAX end Document");
    }

    public List<Worker> getmList(){
        return mList;
    }
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值