XMLParse之基本对象的建立
公司项目很多都是需要对XML进行编辑、解析,时间一久觉得解析时按照固定的标签解析太过繁琐,作者决定通过反射搞一搞快速解析生成XML。
XML分析
XML的结构骨架其实很简单,就是标签的集合。所以我们需要定义出抽象的标签类来(作者的灵感来源是来自Android的View的设计模式)
XML标签基类
XML标签的结构:标签名、标签属性、子标签。
注意:例如:<Device name=""/>
这里的标签名是Device
。标签属性指的是name=""
,所以标签属性应该是key-value
形式。子标签可能有可能没有,所以我们需要一种模式来将他们统一起来设计模式之组合模式
。
好,分析完了,下面来定义类
XMLAttribute - 标签的属性类
只有
name
和value
两个变量
public class XMLAttribute {
private String name;//属性名
private String values;//属性值
//构造方法和getter、setter方法
}
XMLBase - 标签的基类
定义
name
和XMLAttributes
两个变量,XMLAttributes的类型是List,因为一个XML标签可能对应多个属性。
定义transform()
、addKids(XMLBase)
、removeKids(XMLBase)
、showKids()
抽象方法,由子类实现不同处理
public abstract class XMLBase {
protected String name;
protected List<XMLAttribute> XMLAttributes;
public abstract boolean addKids(XMLBase base);
public abstract boolean removeKids(XMLBase base);
public abstract void showKids();
//通过 反射将读取出的xmlbase 实体类转换为 com.lee.xmlbean 优雅 哈哈哈
public abstract Object transform();
//getter和setter方法
{···}
}
好,到此和XML标签有关的基类就建立的差不多了,我们接下来看一下具体的标签实现类。
XML标签实现类
对于XML标签我们按照有无子标签进行分类区别,分为
XMLHasKids
和XMLNoKids
两种,下面分别实现。
XMLNoChilds - 无子标签 标签类
对于无子标签的标签类,只需要继承XMLBase类,处理XMLAttributes集合即可。由于核心代码在
transform()
中,我们仔细看一下
@Override
public Object transform() {
//根据标签名 获取对应的类名
String className = Globals.CLASSNAME+this.name;
Object o = null;
try {
//类反射获取类对象
Class clazz = Class.forName(className);
//实例化类对象
o = clazz.newInstance();
//取到该类中的所有的方法
Method[] methods = clazz.getDeclaredMethods();
//取到该类中的所有的域(变量)
Field[] filds = clazz.getDeclaredFields();
//对于该标签的属性集合进行遍历
for (XMLAttribute XMLAttribute : XMLAttributes) {
String name = XMLAttribute.getName().toLowerCase();
String type = "";
//找到对应的域对象,获取对象类型
for (Field fild : filds) {
if (fild.getName().toLowerCase().equals(name)){
type = fild.getGenericType().toString();
}
}
//找到属性对应的setter方法,进行赋值
for (Method method : methods) {
String mName = method.getName().toLowerCase();
if (("set"+name).equals(mName)) {
valueFormat(type,o,XMLAttribute,method);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return o;
}
XMLHasKids - 含子标签 标签类
对于含有子标签的标签类,我们在继承XMLBase的基础上还需要定义两个集合
List<Object> kids
(子标签转换后对象集合)和List<XMLBase> childs
(子标签集合)。
而对于transform()
需要加入非属性变量的解析,包含集合和非集合的解析。
@Override
public Object transform() {
//根据标签名获取对应的类名称
String className = Globals.CLASSNAME+this.name;
Object o = null;
try {
//通过反射获取标签类类对象
Class clazz = Class.forName(className);
//实例化
o = clazz.newInstance();
//获取全部的方法对象
Method[] methods = clazz.getDeclaredMethods();
//获取全部的域对象
Field[] filds = clazz.getDeclaredFields();
//属性操作 把标签属性写入实例中
for (XMLAttribute XMLAttribute : XMLAttributes) {
String name = XMLAttribute.getName().toLowerCase();
String type = "";
for (Field fild : filds) {
if (fild.getName().toLowerCase().equals(name)){
type = fild.getGenericType().toString();
}
}
for (Method method : methods) {
String mName = method.getName().toLowerCase();
if (("set"+name).equals(mName)){
valueFormat(type,o,XMLAttribute,method);
break;
}
}
}
//非属性,非集合 设置 把当前对象中存在的其他对象的引用数据写入(not list)
for (Method method : methods) {
String mName = method.getName().toLowerCase();
for (XMLBase child : childs) {
String chlName = child.name.toLowerCase();
if (("set"+chlName).equals(mName)){
//调用子节点的transform
Object obj = child.transform();
method.invoke(o,obj);
break;
}
}
}
// 非属性 集合 设置 把当前对象中的集合类引用数据写入
for (Method method : methods) {
String mName = method.getName().toLowerCase();
for (XMLBase child : childs) {
String chlName = child.name.toLowerCase();
if (("set"+chlName+"s").equals(mName)){
kids.add(child.transform());
}
}
if (kids.size()>0){
method.invoke(o,new Object[]{kids});
kids.clear();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return o;
}
到此,需要用到的基础对象都已设计完成,下一篇记录解析过程的设计实现