Android之Pull解析XML

来源:互联网 发布:手机总是弹出淘宝页面 编辑:程序博客网 时间:2024/05/15 17:18

Pull解析器的运行方式是基于事件的模式。在Pull解析过程中返回的是数字,且我们需要自己获取产生的事件然后做相应的操作。

读取到XML的声明返回数字0    START_DOCUMENT;

读取到XML的结束返回返回数字1    END_DOCUMENT;

读取到XML的开始标签返回数字2  START_TAG;

读取到XML的结束标签返回数字3   END_TAG;

读取到XML的文本返回数字4          TEXT;

Pull解析器小巧轻便,解析速度快,简单易用,非常适合在Android移动设备中使用,Android系统内部在解析各种XML时也是用PULL解析器,Android官方推荐开发者们使用PULL解析技术。

PULL的工作原理:

XML PULL提供了开始元素和结束元素。当某个元素开始时,我们可以调用paraser.nextText从XML文档中提取所有字符数据。当解释到一个文档结束时候,自动生成End_Document事件。

常用的XML PULL的接口和类:

XmlPullParser:  Android源码是这样介绍的:XML Pull Parser is an interface that defines parsing functionality provided in <a href="http://www.xmlpull.org/">XMLPULL V1 API</a> (visit this website to learn more about API and its implementations).XML Pull 解析器是一个在XML PULL V1 API 中提供了定义解析功能的接口。

XmlSerializer:它是一个接口,定义了XML信息集的序列。

XmlPullParserFactory:这个类用于在XML PULL V1 API中创建XML PULL 解析器。

XmlPullParserException:抛出单一的XML Pull解析器相关的错误。

如下XML文件:


先看一下我打印出来的日志结果:(项目源代码在下面)


我们从上图看到,XmlPullParser.START_DOCUMENT,与XmlPullParser.END_DOCUMENT只执行了一次。在这个当中发现2,3,4都在不停的执行。可以根据上面Log信息总结一下Pull解析原理。我们就用这个例子来说明一下Pull解析原理。


Pull解析这个XML文件,首先从<?xml version="1.0" encoding="UTF-8"?>开始解析,所以出现数字0,。接下来开始进入标签<apps>显示数字2,接着执行XmlPullParser.next(),得到的是数字4,这一点我纠结了好久,为什么会出现4呢?4代表的是:读取到XML的文本返回数字4          TEXT;  难道<apps>标签后面还隐藏着Text标签么?可以在<apps>后面加上文本?于是我们在<apps>后面加了This is apps.在浏览器中解析如下所示:


原来<apps>后面是可以加Text.这下清楚了!但是在结束标签的时候</id>、</name>、</version>也出现了数字4.我也尝试着加入Text。浏览器解析失败。在Android studio中在开始标签<apps>后面加入Text也会解析出错,这就跟Android中Pull解析机制有关啦!需要我们仔细研究一下源码。

开始项目

服务器放的XML数据:


这里我是用自己电脑上的Tomcat搭建的服务器,文件存放地址:TomCat安装目录/Tomcat7.0/webapps/ROOT/get_data.xml.

项目最终效果:


把服务器返回的XMl文件,用PULL解析器解析,然后显示在UI上。

(1)布局文件activity_main.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context="com.example.pullandxml.MainActivity">    <Button        android:id="@+id/send_request"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:onClick="click"        android:text="Send Request"/>    <ScrollView        android:layout_width="match_parent"        android:layout_height="match_parent">        <TextView            android:id="@+id/response_text"            android:layout_width="match_parent"            android:layout_height="wrap_content" />    </ScrollView></LinearLayout>

(2)MainActivity.java

package com.example.pullandxml;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.util.Xml;import android.view.View;import android.widget.TextView;import android.widget.Toast;import org.xmlpull.v1.XmlPullParser;import org.xmlpull.v1.XmlPullParserFactory;import java.io.StringReader;import okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.Response;public class MainActivity extends AppCompatActivity {    private TextView response_text;    final  static  String TAG="MainActivity";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        response_text = (TextView) this.findViewById(R.id.response_text);    }    public void click(View v) {        sendRequestWithHttpURLConnection();    }    public void sendRequestWithHttpURLConnection() {        new Thread(new Runnable() {            @Override            public void run() {                try {                    OkHttpClient client = new OkHttpClient();                    Request request = new Request.Builder()                            .url("http://10.0.2.2:8080/get_data.xml")                            .build();                    Response response = client.newCall(request).execute();                    String responseData = response.body().string();                    parseXMLWithPull(responseData);                } catch (Exception e) {                    e.printStackTrace();                }            }        }).start();    }    /**     * 用Pull解析XML数据     *     * @param xmlData 服务器返回的数据     */    public void parseXMLWithPull(String xmlData) {        try {            //==========创建XmlPullParser,有两种方式=======================            //方式一:使用工厂类获取到XmlPullParserFactory实例            //XmlPullParserFactory factory = XmlPullParserFactory.newInstance();            //借助XmlPullParserFactory实例得到XmlPullParser对象            //XmlPullParser xmlPullParser = factory.newPullParser();            //方式二:使用android提供的由android.util.Xml创建一个XmlPullParser实例            XmlPullParser xmlPullParser= Xml.newPullParser();            //解析文件输入流            xmlPullParser.setInput(new StringReader(xmlData));            //得到当前的解析事件            int eventType = xmlPullParser.getEventType();            Log.i(TAG,eventType+"");            StringBuilder showResponse = new StringBuilder();            String id = "";            String name = "";            String version = "";            //While循环中不断的解析,如果当前的解析事件不等于XmlPullParser.END_DOCUMENT,说明解析工作还没有完成            while (eventType != XmlPullParser.END_DOCUMENT) {                //通过getName()方法得到当前节点的名字                String nodeName = xmlPullParser.getName();                switch (eventType) {                    //判断当前事件是否为标签元素开始事件                    case XmlPullParser.START_TAG: {                        Log.i(TAG,nodeName);                        if ("id".equals(nodeName)) {                            //通过nextText()方法来获取解析器当前指向元素的下一个文本节点的值                            xmlPullParser.next();                            id = xmlPullParser.getText();                            Log.i(TAG,id);                        } else if ("name".equals(nodeName)) {                            xmlPullParser.next();                            name = xmlPullParser.getText();                            Log.i(TAG,name);                        } else if ("version".equals(nodeName)) {                            xmlPullParser.next();                            version = xmlPullParser.getText();                            Log.i(TAG,version);                        }                    }                    break;                    case XmlPullParser.END_TAG: {  //完成解析某个节点                        Log.i(TAG,nodeName);                        if ("app".equals(nodeName)) {                            showResponse.append("id is " + id + ",name is " + name + ",version is " + version + ";\n");                        }                    }                    break;                    default:                        break;                }                //调用next()方法后可以获取下一个解析事件                eventType = xmlPullParser.next();                Log.i(TAG,eventType+"");            }            showResponseToUI(showResponse.toString());        } catch (Exception e) {            e.printStackTrace();        }    }    private void showResponseToUI(final String response){        runOnUiThread(new Runnable() {            @Override            public void run() {                //在这里进行UI操作,将结果显示到界面上                response_text.setText(response);            }        });    }}

(3)由于项目访问网络用的是OKHttp,所以在模块的build.gradle中,加入下面代码:

 compile 'com.squareup.okhttp3:okhttp:3.4.1'

(4)给项目加上访问网络的权限。AndroidManifest.xml.

<uses-permission android:name="android.permission.INTERNET" />


0 0
原创粉丝点击