android通用xml解析方法

oulin009

oulin009

2016-02-19 10:29

今天图老师小编要跟大家分享android通用xml解析方法,精心挑选的过程简单易学,喜欢的朋友一起来学习吧!

1、为什么需要写一个通用xml解析方法。

当需要解析不同的xml节点。你有可能是在xml解析的时候匹配不同节点并且节点名都是写死的,这样的话你解析不同的节点就需要不同的解析方法。当然这种方式是最简单也是最笨的方法。为了减少代码把代码写得更有质量那么你就需要考虑设计一个通用的xml解析方法。

2、解析思路。

一般情况下,xml的解析结果最好放在一个实体类对象中,那样的话你使用起来非常方便(当然也更OO了),你也可以选择其他的方法把解析结果保存下来,不过个人觉得这种方式是比较好的。在解析过程中你需要做的是什么呢?这是解析的关键。其实就是把要解析的结果设置给对象的属性(成员变量),考虑到这点,那么肯定是需要知道对象有哪些属性啊,那就给实体类加一个方法(其实这里是做一定的规范)用于获得属性。知道了属性名以后下一步当然就是设置这些属性的值。因为不同的实体类的属性不同,所以设置值采用反射机制。大体上的思路就是这个样子。具体代码后面讲。

3、解析xml的格式类型。

文字只写两种xml格式的解析。其他格式你可以参考本文的思路任意发挥。

①只有节点中内容:如

代码如下:

?xml version="1.0" encoding="UTF-8" ?

Result

  StuId30323/StuId

  ClassID10042/ClassID

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

/Result

②只有节点属性:如

代码如下:

?xml version="1.0" encoding="UTF-8" ?

Result

   ProjLst Name="测试1" Id="1" /

   ProjLst Name="测试2" Id="2" /

   ProjLst Name="测试3" Id="3" /

/Result

4、如何实现。

①根据设计思路,你需要一个实体类,但是实体类有一定的规范(为了解析)。所以这些规范还需要实现一些统一的方法,于是就有了一个抽象类: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();

}

}

}

②根据具体的节点类型生成类的成员。这里先看看需要解析的xml。

代码如下:

?xml version="1.0" encoding="UTF-8" ?

  DsXml

  IsLogtrue/IsLog

  GradeID10001/GradeID

  GradeName高一年级/GradeName

  ClassID10010/ClassID

  ClassName高一(01)班/ClassName

  UserID10000/UserID

  UserName张三/UserName

  /DsXml

③对应的实体类。

代码如下:

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" };

}

}

实体类中的是这样规范的:getNodes()返回的是xml的节点名,命名必须相同,并且成员变量名必须和节点名相同。当然这里实现Serializable 接口只是我自己的项目中的需求而已,和本文无关。

④最关键是如何解析。

代码如下:

View Code

/**

 * @description :解析节点中的内容,封装成对象模型。

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

 * @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();

}

}

当然里面的一些变量在类初始化的时候就完成了。如下:

代码如下:

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的数据流。具体的细节可以自己体会一下。这个解析类在一定程度上可以通用,也就是你的xml格式符合“只有节点中内容”那么就可以这么通用。为了方便下文做说明暂且把这种类型的xml称为“类型A”。

⑥说说另一种格式“只有节点属性”如何“通用”解析。为了方便下文做说明暂且把这种类型的xml称为“类型B”。下文所讲的都是针对类型B的相关代码。类型B的xml如下:

代码如下:

View Code

 ?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是一样的)

代码如下:

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中的属性,封装成对象模型。

 * @author : kwzhang

 * @create :2013-2-28

 * @param in

 * @param obj

 * @throws Exception

 * @return :void

 */

public static T extends BaseObj ListT streamParam2Model(InputStream in, T obj) throws Exception {

pullParser.setInput(in, encode);

int eventType = pullParser.getEventType();

ArrayListT list = new ArrayListT(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);

}

ConstructorT constructor = (ConstructorT) obj.getClass().getConstructor();

obj = constructor.newInstance();

break;

case XmlPullParser.END_TAG:

break;

}

eventType = pullParser.next();

}

return list;

}

⑨如何使用类别B的解析。

代码如下:

ArrayListTmInfo  datas = (ArrayListTmInfo) XmlUtils.stream2Tm(result, new TmInfo());

总结:虽然这里只是写了这两种类型,但是可以根据这种反射机制的思路完成更复杂的xml解析。使用的时候一定要注意变量命名的规范。用这样的方式进行解析的话代码设计更优雅,而且xml解析的时候会根据你的变量去解析,而不是写死。

转载自:http://www.cnblogs.com/vanezkw/archive/2013/03/03/2941496.html

展开更多 50%)
分享

猜你喜欢

android通用xml解析方法

编程语言 网络编程
android通用xml解析方法

Android中使用sax解析xml文件的方法

编程语言 网络编程
Android中使用sax解析xml文件的方法

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

android layout XML解析错误的解决方法

编程语言 网络编程
android layout XML解析错误的解决方法

基于Android XML解析与保存的实现

编程语言 网络编程
基于Android XML解析与保存的实现

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

Android开发之XML文件解析的使用

编程语言 网络编程
Android开发之XML文件解析的使用

Android中使用PULL方式解析XML文件深入介绍

编程语言 网络编程
Android中使用PULL方式解析XML文件深入介绍

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

Mysql 默认字符集设置方法(免安装版)

Mysql 默认字符集设置方法(免安装版)

JScript中的undefined和"undefined"的区别

JScript中的undefined和"undefined"的区别
下拉加载更多内容 ↓