android通用xml解析方法
1、為什么需要寫一個(gè)通用xml解析方法。
當(dāng)需要解析不同的xml節(jié)點(diǎn)。你有可能是在xml解析的時(shí)候匹配不同節(jié)點(diǎn)并且節(jié)點(diǎn)名都是寫死的,這樣的話你解析不同的節(jié)點(diǎn)就需要不同的解析方法。當(dāng)然這種方式是最簡單也是最笨的方法。為了減少代碼把代碼寫得更有質(zhì)量那么你就需要考慮設(shè)計(jì)一個(gè)通用的xml解析方法。
2、解析思路。
一般情況下,xml的解析結(jié)果最好放在一個(gè)實(shí)體類對(duì)象中,那樣的話你使用起來非常方便(當(dāng)然也更OO了),你也可以選擇其他的方法把解析結(jié)果保存下來,不過個(gè)人覺得這種方式是比較好的。在解析過程中你需要做的是什么呢?這是解析的關(guān)鍵。其實(shí)就是把要解析的結(jié)果設(shè)置給對(duì)象的屬性(成員變量),考慮到這點(diǎn),那么肯定是需要知道對(duì)象有哪些屬性啊,那就給實(shí)體類加一個(gè)方法(其實(shí)這里是做一定的規(guī)范)用于獲得屬性。知道了屬性名以后下一步當(dāng)然就是設(shè)置這些屬性的值。因?yàn)椴煌膶?shí)體類的屬性不同,所以設(shè)置值采用反射機(jī)制。大體上的思路就是這個(gè)樣子。具體代碼后面講。
3、解析xml的格式類型。
文字只寫兩種xml格式的解析。其他格式你可以參考本文的思路任意發(fā)揮。
①只有節(jié)點(diǎn)中內(nèi)容:如
<?xml version="1.0" encoding="UTF-8" ?>
<Result>
<StuId>30323</StuId>
<ClassID>10042</ClassID>
</Result>
②只有節(jié)點(diǎn)屬性:如
<?xml version="1.0" encoding="UTF-8" ?>
<Result>
<ProjLst Name="測(cè)試1" Id="1" />
<ProjLst Name="測(cè)試2" Id="2" />
<ProjLst Name="測(cè)試3" Id="3" />
</Result>
4、如何實(shí)現(xiàn)。
①根據(jù)設(shè)計(jì)思路,你需要一個(gè)實(shí)體類,但是實(shí)體類有一定的規(guī)范(為了解析)。所以這些規(guī)范還需要實(shí)現(xiàn)一些統(tǒng)一的方法,于是就有了一個(gè)抽象類:BaseObj。
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();
}
}
}
②根據(jù)具體的節(jié)點(diǎn)類型生成類的成員。這里先看看需要解析的xml。
<?xml version="1.0" encoding="UTF-8" ?>
<DsXml>
<IsLog>true</IsLog>
<GradeID>10001</GradeID>
<GradeName>高一年級(jí)</GradeName>
<ClassID>10010</ClassID>
<ClassName>高一(01)班</ClassName>
<UserID>10000</UserID>
<UserName>張三</UserName>
</DsXml>
③對(duì)應(yīng)的實(shí)體類。
View Code
/***********************************************************
*@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" };
}
}
實(shí)體類中的是這樣規(guī)范的:getNodes()返回的是xml的節(jié)點(diǎn)名,命名必須相同,并且成員變量名必須和節(jié)點(diǎn)名相同。當(dāng)然這里實(shí)現(xiàn)Serializable 接口只是我自己的項(xiàng)目中的需求而已,和本文無關(guān)。
④最關(guān)鍵是如何解析。
View Code
/**
* @description :解析節(jié)點(diǎn)中的內(nèi)容,封裝成對(duì)象模型。
* @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();
}
}
當(dāng)然里面的一些變量在類初始化的時(shí)候就完成了。如下:
private static String encode = "utf-8";
public static XmlPullParser pullParser;
static {
try {
pullParser = XmlPullParserFactory.newInstance().newPullParser();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
}
⑤如何使用.如下:
XmlUtils.streamText2Model(result, ActMain.student);
很簡單吧。result就是xml的數(shù)據(jù)流。具體的細(xì)節(jié)可以自己體會(huì)一下。這個(gè)解析類在一定程度上可以通用,也就是你的xml格式符合“只有節(jié)點(diǎn)中內(nèi)容”那么就可以這么通用。為了方便下文做說明暫且把這種類型的xml稱為“類型A”。
⑥說說另一種格式“只有節(jié)點(diǎn)屬性”如何“通用”解析。為了方便下文做說明暫且把這種類型的xml稱為“類型B”。下文所講的都是針對(duì)類型B的相關(guān)代碼。類型B的xml如下:
View Code
<?xml version="1.0" encoding="UTF-8" ?>
<DsXml>
<ProjLst KeliName="測(cè)試1" KeliId="170" SubId="13" ExeTp="1" ExeType="預(yù)習(xí)" ExeDt="2013-2-27" ExeCount="4" SubName="信息技術(shù)" />
<ProjLst KeliName="測(cè)試2" KeliId="154" SubId="13" ExeTp="1" ExeType="預(yù)習(xí)" ExeDt="2012-11-19" ExeCount="2" SubName="信息技術(shù)" />
<ProjLst KeliName="測(cè)試2" KeliId="150" SubId="13" ExeTp="3" ExeType="課后" ExeDt="2012-11-15" ExeCount="2" SubName="信息技術(shù)" />
</DsXml>
⑦類型B實(shí)體類如下:(其實(shí)和類型A是一樣的)
View Code
/***********************************************************
*@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解析方法如下:
View Code
/**
* @description : 解析xml中的屬性,封裝成對(duì)象模型。
* @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的解析。
ArrayList<TmInfo> datas = (ArrayList<TmInfo>) XmlUtils.stream2Tm(result, new TmInfo());
總結(jié):雖然這里只是寫了這兩種類型,但是可以根據(jù)這種反射機(jī)制的思路完成更復(fù)雜的xml解析。使用的時(shí)候一定要注意變量命名的規(guī)范。用這樣的方式進(jìn)行解析的話代碼設(shè)計(jì)更優(yōu)雅,而且xml解析的時(shí)候會(huì)根據(jù)你的變量去解析,而不是寫死。
轉(zhuǎn)載自:http://www.cnblogs.com/vanezkw/archive/2013/03/03/2941496.html
- 基于Android XML解析與保存的實(shí)現(xiàn)
- android layout XML解析錯(cuò)誤的解決方法
- Android中使用sax解析xml文件的方法
- Android 解析XML 文件的四種方法總結(jié)
- Android中使用PULL方式解析XML文件深入介紹
- Android提高之XML解析與生成實(shí)例詳解
- Android 使用Pull方法解析XML文件的方法
- android編程之XML文件解析方法詳解(附源碼)
- Android使用Pull解析器解析xml文件的實(shí)現(xiàn)代碼
- 19個(gè)Android常用工具類匯總
- android 一些工具類匯總
- Android開發(fā)中解析xml文件XmlUtils工具類與用法示例
相關(guān)文章
Android design包自定義tablayout的底部導(dǎo)航欄的實(shí)現(xiàn)方法
這篇文章主要介紹了Android design包自定義tablayout的底部導(dǎo)航欄的實(shí)現(xiàn)方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下2017-01-01Android 仿小米鎖屏實(shí)現(xiàn)九宮格解鎖功能(無需圖片資源)
最近公司要求做個(gè)九宮格解鎖,本人用的是小米手機(jī),看著他那個(gè)設(shè)置鎖屏九宮格很好看,就做了該組件,不使用圖片資源,純代碼實(shí)現(xiàn),感興趣的朋友參考下吧2016-12-12Android Path繪制貝塞爾曲線實(shí)現(xiàn)QQ拖拽泡泡
本文主要介紹Android Path繪制貝塞爾曲線,這里整理相關(guān)資料并運(yùn)用貝塞爾曲線實(shí)現(xiàn)QQ拖拽泡泡的示例,有興趣的小伙伴可以參考下2016-09-09Android 解決使用SearchView時(shí)軟鍵盤不支持actionSearch的問題
本文主要介紹使用SearchView時(shí)軟鍵盤不支持actionSearch,這里提供了解決方案,希望能幫助開發(fā)Android應(yīng)用的同學(xué)2016-07-07Android實(shí)現(xiàn)收到新短信后自動(dòng)發(fā)郵件功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)收到新短信后自動(dòng)發(fā)郵件功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05不允許錯(cuò)過的Anndroid技術(shù)經(jīng)驗(yàn)60條
不允許錯(cuò)過的Anndroid技術(shù)經(jīng)驗(yàn)60條,與大家分享,希望可以提高大家Android開發(fā)水平,感興趣的朋友可以參考一下2016-02-02Android檢測(cè)url地址是否可達(dá)的兩種方法
今天小編就為大家分享一篇Android檢測(cè)url地址是否可達(dá)的兩種方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-01-01