50. 【Android教程】xml 数据解析

xml 是一种标记扩展语言(Extension Mark-up Language),学到这里大家对 xml 语言一定不陌生,但是它在 Android 中的运用其实只是冰山一角。抛开 Android,XML 也被广泛运用于各种数据结构中。在运用 xml 编写 Android 布局的过程中,大家有没有好奇我们写的 LinearLayout 或者 RelativeLayout 等布局是怎么变系统解析成 UI 样式的?这一节我们来揭晓谜底。

1. xml 的优势

XML 是一种标记语言,我们目前接触最多的用法就是用来写布局文件。但其实,xml 被广泛用于网络数据传输中,它是一种非常流行的网络数据格式。比如我们可以使用上一节学到的 HttpURLConnect 去向 Service 发起一个 Http 请求,那么 Service 就可以将数据用 xml 的形式下发,无论是从保存还是从解析的角度,xml 都提供了极大的便利。

2. xml 的解析方式

Android 提供了 3 种类型的解析器:DOMSAXXMLPullParser 。在这三种类型中,唯 XMLPullParser 以其高效易用两大优点被 Android 官方推荐,在实际开发中绝大多数场景都是使用 XMLPullParser,所以本节主要介绍 XMLPullParser 的使用方法。

3. XMLPullParser 的组成部分

虽然写过很多 xml 布局,但是还是来系统的看一下 xml 的组成部分,一个 xml 文件通常由 4 个部分组成:

  • **prolog :**通常在 xml 文件的第一行,包含一些文件的描述信息,比如版本号、编码格式等
  • **Events:**以各个 Tag 开头和结尾的部分
  • **Text:**介于两个 Tag 之间的内容
  • **Attributes:**用来描述每个 Tag 的属性

4. XML 解析示例

4.1 XML 样本

下面我们来解析一个非常简单的 XML,如下:

复制代码
<?xml version="1.0" encoding="utf-8"?>
<heros>
    <hero id="1">
        <name>
            马超
        </name>
        <description>
            刺客
        </description>
    </hero>

    <hero id="2">
        <name>
            妲己
        </name>
        <description>
            法师
        </description>
    </hero>

    <hero id="3">
        <name>
            鲁班
        </name>
        <description>
            射手
        </description>
    </hero>

</heros>

4.2 XML 解析

以上 xml 是一个英雄列表,包含了 3 个英雄对象,每个英雄对象包含名字和描述,下面开始进行解析。

复制代码
    private ArrayList<Hero> parseXML(XmlPullParser parser) throws XmlPullParserException, IOException {
        ArrayList<Hero> heros = null;
        int eventType = parser.getEventType();
        Hero hero = null;

        // 判断是否结束
        while (eventType != XmlPullParser.END_DOCUMENT) {
            String name;
            switch (eventType) {
                case XmlPullParser.START_DOCUMENT:
                    // 处理开始标签,在开始的时候创建英雄List
                    heros = new ArrayList();
                    break;
                case XmlPullParser.START_TAG:
                    // 处理tag开始,在这里接收英雄及英雄属性
                    name = parser.getName();
                    if (name.equals("hero")) {
                        hero = new Hero();
                        hero.id = parser.getAttributeValue(null, "id");
                    } else if (hero != null) {
                        if (name.equals("name")) {
                            hero.name = parser.nextText();
                        } else if (name.equals("description")) {
                            hero.description = parser.nextText();
                        }
                    }
                    break;
                case XmlPullParser.END_TAG:
                    // 标签结束,将英雄添加到英雄列表
                    name = parser.getName();
                    if (name.equalsIgnoreCase("hero") && hero != null) {
                        heros.add(hero);
                    }
            }
            // 处理下一个标签
            eventType = parser.next();
        }
        return heros;
    }

parseXML方法中,首先解析 prelog,在这里创建英雄列表 List,然后一次解析英雄标签及内部属性,最后解析完一个英雄立即存入 List 中。

4.3 MainActivity 主逻辑

现在已经写好了 XML 解析方法,那么 MainActivity 的逻辑就非常简单了,我们只需写一个带有一个 Button 的布局,用于触发 XML 的解析,然后在onCreate()中调用设置监听器,并在监听器中调用解析逻辑即可,最后将解析完的内容输入到 Logcat:

复制代码
package com.emercy.myapplication;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

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;

public class MainActivity extends Activity {

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

        findViewById(R.id.parse_xml).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                XmlPullParserFactory pullParserFactory = null;

                try {
                    try {
                        pullParserFactory = XmlPullParserFactory.newInstance();
                    } catch (XmlPullParserException e) {
                        e.printStackTrace();
                    }
                    XmlPullParser parser = pullParserFactory.newPullParser();

                    InputStream in_s = getApplicationContext().getAssets().open("heros.xml");
                    parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
                    parser.setInput(in_s, null);

                    ArrayList<Hero> heros = parseXML(parser);

                    String text = "";

                    for (Hero hero : heros) {

                        text += "id : " + hero.getId() + " name : " + hero.getName() + " description : " + hero.getDescription() + "\n";
                    }
                    Log.d("\nXML Parser", text);
                } catch (XmlPullParserException | IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

编译运行,点击"解析 xml",查看 Logcat 的输出:

可以看到 log 的输出和 XML 的定义一模一样,到这里 XML 的内容就被解析到 heros 的 list 中了。

5. 小结

本节介绍了一个以前经常接触的数据格式,在 Andorid 中我们的布局可以很方便的用 XML 来编写,重新回到本节开头的问题,Android 系统是如何将我们写好的 XML 布局转换成 UI 样式的呢?是否也可以通过XmlPullParser来完成?

当然,除了编写 Android 布局之外,XML 也是网络传输中常用的数据格式,我们可以将需要的数据通过 XML 格式存储,然后通过上一节学习的 HttpURLConnection 来进行传输。除了 XML,还有另一种数据格式非常实用,我们将在下一节揭晓。

相关推荐
Digitally8 小时前
如何用5种实用方法将电脑上的音乐传输到安卓手机
android·智能手机·电脑
HahaGiver6669 小时前
Unity与Android原生交互开发入门篇 - 打开Unity游戏的设置
android·unity·交互
2501_915909069 小时前
WebView 调试工具全解析,解决“看不见的移动端问题”
android·ios·小程序·https·uni-app·iphone·webview
IT乐手10 小时前
android 下载管理工具类
android
2501_9151063211 小时前
App 怎么上架 iOS?从准备资料到开心上架(Appuploader)免 Mac 上传的完整实战流程指南
android·macos·ios·小程序·uni-app·iphone·webview
科技峰行者12 小时前
安卓16提前发布能否改写移动生态格局
android
蒲公英少年带我飞12 小时前
Android NDK 编译 protobuf
android
沐怡旸13 小时前
【底层机制】ART虚拟机深度解析:Android运行时的架构革命
android·面试
小禾青青13 小时前
uniapp安卓打包遇到报错:Uncaught SyntaxError: Invalid regular expression: /[\p{L}\p{N}]/
android·uni-app
studyForMokey14 小时前
【Kotlin内联函数】
android·开发语言·kotlin