XML在各種開發中得到了廣泛的應用,其實Android也是一樣的,XML作為重要的數據傳輸,如何讀寫XML已經成為Android開發中的一項重要技術,今天武林技術頻道小編將和大家一起探討android通用xml解析的幾個方法。
1、為什么需要寫一個通用xml解析方法。
當需要解析不同的xml節點。你有可能是在xml解析的時候匹配不同節點并且節點名都是寫死的,這樣的話你解析不同的節點就需要不同的解析方法。當然這種方式是最簡單也是最笨的方法。為了減少代碼把代碼寫得更有質量那么你就需要考慮設計一個通用的xml解析方法。
2、解析思路。
一般情況下,xml的解析結果最好放在一個實體類對象中,那樣的話你使用起來非常方便(當然也更OO了),你也可以選擇其他的方法把解析結果保存下來,不過個人覺得這種方式是比較好的。在解析過程中你需要做的是什么呢?這是解析的關鍵。其實就是把要解析的結果設置給對象的屬性(成員變量),考慮到這點,那么肯定是需要知道對象有哪些屬性啊,那就給實體類加一個方法(其實這里是做一定的規范)用于獲得屬性。知道了屬性名以后下一步當然就是設置這些屬性的值。因為不同的實體類的屬性不同,所以設置值采用反射機制。大體上的思路就是這個樣子。具體代碼后面講。
3、解析xml的格式類型。
文字只寫兩種xml格式的解析。其他格式你可以參考本文的思路任意發揮。
①只有節點中內容:如
?
?
<Result>
<StuId>30323</StuId>
<ClassID>10042</ClassID>
</Result>
②只有節點屬性:如
?
?
?
<Result>
? <ProjLst Name="測試1" Id="1" />
? <ProjLst Name="測試2" Id="2" />
? <ProjLst Name="測試3" Id="3" />
</Result>
4、如何實現。
?
①根據設計思路,你需要一個實體類,但是實體類有一定的規范(為了解析)。所以這些規范還需要實現一些統一的方法,于是就有了一個抽象類:BaseObj。
?
?
/***********************************************************
?*@description : This class function is TODO
?*
?* @create author : kwzhang
?* @create date?? :2013-2-28
?* @modify author :
?* @modify date?? :
?* @contact: vanezkw@163.com
?*
?**********************************************************/
package com.vane.elearning.model;
?
import java.lang.reflect.Field;
?
/**
?* @author kwzhang
?*
?*/
public abstract class BaseObj {
public abstract String[] getNodes();
public void setParamater(String tag, Object value) {
try {
Field field = getClass().getField(tag);
field.setAccessible(true);
field.set(this, value);
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
②根據具體的節點類型生成類的成員。這里先看看需要解析的xml。
?
?
?
? <DsXml>
? <IsLog>true</IsLog>
? <GradeID>10001</GradeID>
? <GradeName>高一年級</GradeName>
? <ClassID>10010</ClassID>
? <ClassName>高一(01)班</ClassName>
? <UserID>10000</UserID>
? <UserName>張三</UserName>
? </DsXml>
③對應的實體類。
?
?
?
/***********************************************************
?*@description : This class function is TODO
?*
?* @create author : kwzhang
?* @create date?? :2013-2-28
?* @modify author :
?* @modify date?? :
?* @contact: vanezkw@163.com
?*
?**********************************************************/
package com.vane.elearning.model;
import java.io.Serializable;
/**
?* @author kwzhang
?*
?*/
public class Student extends BaseObj implements Serializable {
private static final long serialVersionUID = 1L;
public String GradeID, GradeName, ClassID, ClassName, UserID, UserName;
public Student() {
}
@Override
public String[] getNodes() {
return new String[] { "GradeID", "GradeName", "ClassID", "ClassName", "UserID", "UserName" };
}
}
實體類中的是這樣規范的:getNodes()返回的是xml的節點名,命名必須相同,并且成員變量名必須和節點名相同。當然這里實現Serializable 接口只是我自己的項目中的需求而已,和本文無關。
?
④最關鍵是如何解析。
?
?
/**
?* @description :解析節點中的內容,封裝成對象模型。
?* @author : kwzhang
?* @create :2013-2-28
?* @param in
?* @param obj
?* @throws Exception
?* @return :void
?*/
public static <T extends BaseObj> void streamText2Model(InputStream in, T obj) throws Exception {
pullParser.setInput(in, encode);
int eventType = pullParser.getEventType();
String[] nodes = obj.getNodes();
String nodeName = null;
boolean success = true;
while (eventType != XmlPullParser.END_DOCUMENT && success) {
switch (eventType) {
case XmlPullParser.START_DOCUMENT:
break;
case XmlPullParser.START_TAG:
nodeName = pullParser.getName();
break;
case XmlPullParser.TEXT:
if ("IsLog".equals(nodeName) && pullParser.getText().equals("false")) {
success = false;
break;
}
for (int i = 0; i < nodes.length; i++) {
if (nodes[i].equals(nodeName)) {
obj.setParamater(nodeName, pullParser.getText());
}
}
break;
case XmlPullParser.END_TAG:
break;
}
eventType = pullParser.next();
}
}
當然里面的一些變量在類初始化的時候就完成了。如下:
?
?
?
public static XmlPullParser pullParser;
static {
try {
pullParser = XmlPullParserFactory.newInstance().newPullParser();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
}
⑤如何使用.如下:
?
?
很簡單吧。result就是xml的數據流。具體的細節可以自己體會一下。這個解析類在一定程度上可以通用,也就是你的xml格式符合“只有節點中內容”那么就可以這么通用。為了方便下文做說明暫且把這種類型的xml稱為“類型A”。
?
⑥說說另一種格式“只有節點屬性”如何“通用”解析。為了方便下文做說明暫且把這種類型的xml稱為“類型B”。下文所講的都是針對類型B的相關代碼。類型B的xml如下:
?
?
?<?xml version="1.0" encoding="UTF-8" ?>
? <DsXml>
? <ProjLst KeliName="測試1" KeliId="170" SubId="13" ExeTp="1" ExeType="預習" ExeDt="2013-2-27" ExeCount="4" SubName="信息技術" />
? <ProjLst KeliName="測試2" KeliId="154" SubId="13" ExeTp="1" ExeType="預習" ExeDt="2012-11-19" ExeCount="2" SubName="信息技術" />
? <ProjLst KeliName="測試2" KeliId="150" SubId="13" ExeTp="3" ExeType="課后" ExeDt="2012-11-15" ExeCount="2" SubName="信息技術" />
? </DsXml>
⑦類型B實體類如下:(其實和類型A是一樣的)
?
?
?
/***********************************************************
?*@description : This class function is TODO
?*
?* @create author : kwzhang
?* @create date?? :2013-2-28
?* @modify author :
?* @modify date?? :
?* @contact: vanezkw@163.com
?*
?**********************************************************/
package com.vane.elearning.model;
import java.io.Serializable;
/**
?* @author kwzhang
?*
?*/
public class Keli extends BaseObj implements Serializable {
private static final long serialVersionUID = 1L;
public String KeliName, KeliId, SubId, ExeTp, ExeType, ExeDt, ExeCount, SubName;
public Keli() {
}
@Override
public String[] getNodes() {
return new String[] { "KeliName", "KeliId", "SubId", "ExeTp", "ExeType", "ExeDt", "ExeCount", "SubName" };
}
}
⑧類型B解析方法如下:
?
?
?
/**
?* @description : 解析xml中的屬性,封裝成對象模型。
?* @author : kwzhang
?* @create :2013-2-28
?* @param in
?* @param obj
?* @throws Exception
?* @return :void
?*/
public static <T extends BaseObj> List<T> streamParam2Model(InputStream in, T obj) throws Exception {
pullParser.setInput(in, encode);
int eventType = pullParser.getEventType();
ArrayList<T> list = new ArrayList<T>(4);
String[] nodes = obj.getNodes();
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {
case XmlPullParser.START_DOCUMENT:
break;
case XmlPullParser.START_TAG:
String name = pullParser.getName();
boolean flag = false;
if (null == name || name.equals("")) {
break;
}
for (int i = 0; i < nodes.length; i++) {
String value = pullParser.getAttributeValue(null, nodes[i]);
flag |= (null != value);
obj.setParamater(nodes[i], value);
}
if (flag) {
list.add(obj);
}
Constructor<T> constructor = (Constructor<T>) obj.getClass().getConstructor();
obj = constructor.newInstance();
break;
case XmlPullParser.END_TAG:
break;
}
eventType = pullParser.next();
}
return list;
}
⑨如何使用類別B的解析。
?
?
?
總結:雖然今天武林技術頻道小編只寫了這兩種類型,但是可以基于這種反射機制完成更復雜的XML解析。
新聞熱點
疑難解答