亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

全部開發者教程

Android 入門教程

菜單類控件
菜單:Menu
并發編程
多線程

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 種類型的解析器:DOM、SAXXMLPullParser。在這三種類型中,唯 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 的輸出:

xml

可以看到 log 的輸出和 XML 的定義一模一樣,到這里 XML 的內容就被解析到 heros 的 list 中了。

5. 小結

本節介紹了一個以前經常接觸的數據格式,在 Andorid 中我們的布局可以很方便的用 XML 來編寫,重新回到本節開頭的問題,Android 系統是如何將我們寫好的 XML 布局轉換成 UI 樣式的呢?是否也可以通過XmlPullParser來完成?
當然,除了編寫 Android 布局之外,XML 也是網絡傳輸中常用的數據格式,我們可以將需要的數據通過 XML 格式存儲,然后通過上一節學習的 HttpURLConnection 來進行傳輸。除了 XML,還有另一種數據格式非常實用,我們將在下一節揭曉。