全国协议5人面授小班,企业级独立开发考核,转业者的IT软件工程师基地 登录/注册 | 如何报名
当前位置: Java   >  xml 数据解析
admin · 更新于 2021-08-06

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>
代码块
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

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;
    }
代码块
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

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();
                }
            }
        });
    }}
代码块
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57


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

5. 小结

本节介绍了一个以前经常接触的数据格式,在 Andorid 中我们的布局可以很方便的用 XML 来编写,重新回到本节开头的问题,Android 系统是如何将我们写好的 XML 布局转换成 UI 样式的呢?是否也可以通过XmlPullParser来完成?
当然,除了编写 Android 布局之外,XML 也是网络传输中常用的数据格式,我们可以将需要的数据通过 XML 格式存储,然后通过上一节学习的 HttpURLConnection 来进行传输。除了 XML,还有另一种数据格式非常实用,我们将在下一节揭晓。


为什么选择汉码未来