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
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
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

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