Android-XmlPullParser解析XML

Android-XmlPullParser解析XML

前言

Android提供了XmlPullParser作为XML的解析器。以Android的布局xml为例,我们可以把Android的XML抽象成

我们把XML的节点进行抽象WidgetModel类。


    public class WidgetModel {

        private WidgetModel parent;// 父节点

        private String widgetName;// widgetName: RelativeLayout , ImageView .etc
        private List<WidgetModel> children;// 布局内部的控件
        private Map<String, String> properties;// 控件的属性

        ...

那么,如何将一个XML解析出来呢?以如下XML为例:


    <?xml version="1.0" encoding="utf-8"?>
    <android.support.design.widget.CoordinatorLayout  xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:context="com.example.mochuanzhb.myapplication.MainActivity">

    <android.support.design.widget.AppBarLayout  android:layout_height="wrap_content" android:layout_width="match_parent" android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar  android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main"/>

    <android.support.design.widget.FloatingActionButton  android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="@dimen/fab_margin" android:src="@android:drawable/ic_dialog_email" />

    </android.support.design.widget.CoordinatorLayout>

解析的Utils代码如下:


    import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;

/** * @version mochuan.zhb on 2016/3/21. * @Author Zheng Haibo * @PersonalWebsite http://www.mobctrl.net * @Description 使用xml的pull方式,进行xml解析 */
public class XmlPullParseTools {

    /** * Use XmlPullParse parse the xml * * @param inputStream * @return */
    public static WidgetModel parseXml(InputStream inputStream) {
        Stack<WidgetModel> widgetModels = new Stack<WidgetModel>();//store the tree node
        try {
            XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
            parser.setInput(inputStream, null);
            int eventType = parser.getEventType();
            while (eventType != XmlPullParser.END_DOCUMENT) {
                switch (eventType) {
                    case XmlPullParser.START_DOCUMENT:
                        Utils.LOG("###START_DOCUMENT");
                        break;
                    case XmlPullParser.START_TAG://push
                        WidgetModel node = createWidgetModel(parser);
                        widgetModels.push(node);
                        break;
                    case XmlPullParser.END_TAG://pop
                        String endTag = parser.getName();
                        Utils.LOG("###END_TAG tagName = " + endTag);
                        wrappedWidgetModel(widgetModels);
                        break;
                    case XmlPullParser.END_DOCUMENT:
                        Utils.LOG("###END_DOCUMENT");
                        break;
                }
                eventType = parser.next();
            }
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return widgetModels.pop();//pop the root of tree
    }

    public static WidgetModel parseXml(String xml) {
        return parseXml(new ByteArrayInputStream(xml.getBytes()));
    }

    /** * build tree * * @param widgetModels */
    private static void wrappedWidgetModel(Stack<WidgetModel> widgetModels) {
        Utils.LOG("###wrappedWidgetModel size = " + widgetModels.size());
        if (widgetModels.size() == 1) {
            return;
        }
        WidgetModel child = widgetModels.pop();
        WidgetModel parent = widgetModels.peek();
        List<WidgetModel> children = parent.getChildren();
        if (children == null) {
            children = new ArrayList<WidgetModel>();
        }
        children.add(child);
        parent.setChildren(children);
        child.setParent(parent);
    }

    /** * create one tree node * * @param parser * @return */
    private static WidgetModel createWidgetModel(XmlPullParser parser) {
        String widgetName = parser.getName();
        Utils.LOG("###START_TAG widgetName = " + widgetName);
        WidgetModel node = new WidgetModel();
        node.setWidgetName(widgetName);
        Map<String, String> properties = new LinkedHashMap<String, String>();
        int count = parser.getAttributeCount();
        for (int i = 0; i < count; i++) {
            String key = parser.getAttributeName(i);
            String value = parser.getAttributeValue(i);
            Utils.LOG("###printAttribute= (" + key + "," + value + ")");
            properties.put(key, value);
        }
        node.setProperties(properties);
        return node;
    }


    public static void printWidgetModel(WidgetModel widgetModel) {
        if (widgetModel == null) {
            return;
        }
        Utils.LOG("###widgetName = " + widgetModel.getWidgetName());
        for (Map.Entry<String, String> entry : widgetModel.getProperties().entrySet()) {
            Utils.LOG("###" + entry.getKey() + "," + entry.getValue());
        }
        if (widgetModel.getChildren() != null) {
            for (WidgetModel child : widgetModel.getChildren()) {
                printWidgetModel(child);
            }
        }
    }


    }

调用parseXml方法之后,XML就解析为以WidgetModel为根节点的多叉树。可以调用printWidgetModel 方法,打印多叉树。

你可能感兴趣的:(xml,android)