zoukankan      html  css  js  c++  java
  • Android之SAX解析XML

    一.SAX解析方法介绍

      SAX(Simple API for XML)是一个解析速度快并且占用内存少的XML解析器,非常适合用于Android等移动设备。

      SAX解析器是一种基于事件的解析器,事件驱动的流式解析方式是,从文件的开始顺序解析到文档的结束,不可暂停或倒退。它的核心是事件处理模式,主要是围绕着事件源以及事件处理器来工作的。当事件源产生事件后,调用事件处理器相应的处理方式,一个事件就可以得到处理。在事件源调用事件处理器中特定方法的时候,还要传递给事件处理器相应事件的状态信息,这样事件处理器才能够根据提供的事件信息来决定自己的行为。并且,它并不需要解析完整个文档,在按内容顺序解析文档的过程中,SAX会判断当前读到的字符是否合法XML语法中的某部分,如果符合就会触发事件。所谓事件,其实就是一些回调(callback)方法,这些方法(事件)定义在ContentHandler接口。

      在SAX接口中,事件源是org.xml.sax包中的XMLReader,它通过parser()方法来解析XML文档,并产生事件。事件处理器是org.xml.sax包中ContentHandle、DTDHandler、ErrorHandler以及EntityResolver这4个接口。XMLReader通过相应事件处理器注册方法setXXX()来完成的与ContentHandle、DTDHandler、ErrorHandler以及EntityResolver这4个接口的连接。

      什么是事件驱动模式?它将XML文档转换成一系列的事件,由单独的事件处理器来决定如何处理。一个可以产生事件的对象叫做事件源,而一个可以针对事件做出响应的对象就被叫做事件处理器。

      优点:不用实现调入整个文档,占用资源少。尤其在嵌入式环境中,如android,极力推荐使用SAX解析。

      缺点:不像DOM解析一样将文档长期驻留在内存中,数据不是持久的。如果事件过后没有保存数据,数据就会丢失。

      使用场合:机器有性能限制。

    二、SAX解析步骤

             1.创建SAXParserFactory对象
    SAXParserFactory spf = SAXParserFactory.newInstance();
             2.根据SAXParserFactory.newSAXParser()方法返回一个SAXParser解析器
    SAXParser saxParser = spf.newSAXParser();
             3.实例为一个DefaultHandler对象
    public class XMLContentHandler extends DefaultHandler {  
    
        //接收文档开始的通知。当遇到文档的开头的时候,调用这个方法,可以在其中做一些预处理。   
        @Override   
         public void startDocument() throws SAXException {
            ...
        }
      //接收元素开始的通知。当读到一个开始标签的时候,会触发这个方法。其中uri表示元素的命名空间;
      //localName表示元素的本地名称(不带前缀);qName表示元素的限定名(带前缀);attrs表示元素的属性集合。
        @Override
        public void startElement(String uri, String localName, String qName,
     Attributes attributes) throws SAXException {
            ...
        }
      //接收字符数据的通知。改方法用来处理在XML文件中读到的内容,第一个参数用来存放文件的内容,后面两个参数
      //是读到的字符串在这个数组中的起始位置和长度。使用newSreing(ch,start,length)就可以获取内容。
       @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            ...
        }
      //接收文档的结尾的通知。在遇到结束标签的时候,调用这个方法。其中,uri表示元素的命名空间;
      //localName表示元素的本地名称(不带前缀);name表示元素的限定名(带前缀)。
      @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            ...
        }
             4.调用SAXParser的parser方法从输入源中获取到XML数据
     saxParser.parse(inputStream, handler);
     inputStream.close();

            也可以使用XMLReader的parse方法从输入源中获取到XML数据。

      5.通过DefaultHandler返回我们需要的数据集合。
    handler.getPersons();

    三、SAX解析XML代码

    1.创建一个XML文件itcase.xml,并将其放在res/raw文件夹下。
    <?xml version="1.0" encoding="UTF-8"?>
    <persons>
        <person id="23">
            <name>liming</name>
            <age>30</age>
        </person>
        <person id="20">
            <name>lixiangmei</name>
            <age>25</age>
        </person>
    </persons>

    如果没有raw文件夹,就在res文件夹下创建一个raw文件夹,并创建xml文件。

    2.修改视图
    <Button
            android:id="@+id/sax_button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="@dimen/fab_margin"
            android:gravity="center_horizontal"
            android:text="@string/SAX" />
    <Button
            android:id="@+id/sax_button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="@dimen/fab_margin"
            android:gravity="center_horizontal"
            android:text="@string/SAX" />
    <TextView
            android:id="@+id/text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!" />
    3.添加XMLContentHandler类
    package com.zhangmiao.analyzexmldemo;
    
    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 zhangmiao on 2016/12/13.
     */
    public class XMLContentHandler extends DefaultHandler {
    
        private List<Person> persons = null;
        private Person currentPerson;
        private String tagName = null;
    
        public List<Person> getPersons() {
            return persons;
        }
    
        @Override
        public void startDocument() throws SAXException {
            persons = new ArrayList<>();
        }
    
        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            if (localName.equals("person")) {
                currentPerson = new Person();
                currentPerson.setId(Integer.parseInt(attributes.getValue("id")));
            }
            this.tagName = localName;
        }
    
        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            if (tagName != null) {
                String data = new String(ch, start, length);
                if (tagName.equals("name")) {
                    this.currentPerson.setName(data);
                } else if (tagName.equals("age")) {
                    this.currentPerson.setAge(Short.parseShort(data));
                }
            }
        }
    
        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            if (localName.equals("person")) {
                persons.add(currentPerson);
                currentPerson = null;
            }
            this.tagName = null;
        }
    }
    4.添加AnalyzeSAM类
    package com.zhangmiao.analyzexmldemo;
    
    import org.xml.sax.InputSource;
    import org.xml.sax.XMLReader;
    
    import java.io.InputStream;
    import java.util.List;
    
    import javax.xml.parsers.SAXParser;
    import javax.xml.parsers.SAXParserFactory;
    
    /**
     * Created by zhangmiao on 2016/12/14.
     */
    public class AnalyzeSAX {
    
        public static List<Person> readXML(InputStream inputStream) {
            try {
                SAXParserFactory spf = SAXParserFactory.newInstance();
                SAXParser saxParser = spf.newSAXParser();
                XMLContentHandler handler = new XMLContentHandler();
                saxParser.parse(inputStream, handler);
                inputStream.close();
                return handler.getPersons();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        public static List<Person> readXML(InputSource inputSource) {
            try {
                SAXParserFactory spf = SAXParserFactory.newInstance();
                SAXParser saxParser = spf.newSAXParser();
                XMLReader reader = saxParser.getXMLReader();
                XMLContentHandler handler = new XMLContentHandler();
                reader.setContentHandler(handler);
                reader.parse(inputSource);
                inputSource.getByteStream().close();
                return handler.getPersons();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    5.修改MainActivity类
    package com.zhangmiao.analyzexmldemo;
    
    import android.os.Bundle;
    import android.support.design.widget.FloatingActionButton;
    import android.support.design.widget.Snackbar;
    import android.support.v7.app.AppCompatActivity;
    import android.support.v7.widget.Toolbar;
    import android.util.Log;
    import android.view.View;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.widget.Button;
    import android.widget.TextView;
    
    import org.xml.sax.InputSource;
    
    import java.io.BufferedWriter;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.io.OutputStreamWriter;
    import java.io.StringWriter;
    import java.util.List;
    
    import javax.xml.parsers.SAXParser;
    import javax.xml.parsers.SAXParserFactory;
    
    public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    
        private static final String TAG = "AnalyzeXMLDemo";
    
        private TextView mTextView;
    
        private InputStream inputStream;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            Log.v(TAG, "onCreate");
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
            setSupportActionBar(toolbar);
    
            FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
            fab.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                            .setAction("Action", null).show();
                }
            });
    
            Button saxButton1 = (Button) findViewById(R.id.sax_button1);
            Button saxButton2 = (Button) findViewById(R.id.sax_button2);
            mTextView = (TextView) findViewById(R.id.text);
    
            saxButton1.setOnClickListener(this);
            saxButton2.setOnClickListener(this);
        }
    
        @Override
        public void onClick(View v) {
            String result = "";
            inputStream = getResources().openRawResource(R.raw.itcase);
            switch (v.getId()) {
                case R.id.sax_button1:
                    result += "--------- SAX1 ---------" + "
    ";
                    if (inputStream == null) {
                        result = "inputStream is null";
                    } else {
                        List<Person> personList = AnalyzeSAX.readXML(inputStream);
                        if (personList != null) {
                            for (int i = 0; i < personList.size(); i++) {
                                String message = "id = " + personList.get(i).getId() + " , name = " + personList.get(i).getName()
                                        + " , age = " + personList.get(i).getAge() + ".
    ";
                                result += message;
                            }
                        }
                    }
                    mTextView.setText(result);
                    break;
                case R.id.sax_button2:
                    result += "--------- SAX2 ---------" + "
    ";
                    InputSource inputSource = new InputSource();
                    inputSource.setByteStream(inputStream);
                    if (inputSource == null) {
                        result = "inputStream is null";
                    } else {
                        List<Person> personList = AnalyzeSAX.readXML(inputSource);
                        if (personList != null) {
                            for (int i = 0; i < personList.size(); i++) {
                                String message = "id = " + personList.get(i).getId() + " , name = " + personList.get(i).getName()
                                        + " , age = " + personList.get(i).getAge() + ".
    ";
                                result += message;
                            }
                        }
                    }
                    mTextView.setText(result);
                    break;
                default:
                    break;
            }
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.menu_main, menu);
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            int id = item.getItemId();
    
            //noinspection SimplifiableIfStatement
            if (id == R.id.action_settings) {
                return true;
            }
    
            return super.onOptionsItemSelected(item);
        }
    }

     参考文章:

    http://www.open-open.com/lib/view/open1392780226397.html

    http://www.cnblogs.com/weixing/archive/2013/08/07/3243366.html

    http://www.tuicool.com/articles/IvQvyq

  • 相关阅读:
    怎样用HTML5 Canvas制作一个简单的游戏
    js面向对象
    javascript闭包
    javascript变量的作用域
    5-22
    5-23
    14-5-21 硬代码
    14-5-19 类和对象
    array
    生成干扰线
  • 原文地址:https://www.cnblogs.com/zhangmiao14/p/6183505.html
Copyright © 2011-2022 走看看