基于Dom4J实现XML快速解析(一)

XMLParse之基本对象的建立

公司项目很多都是需要对XML进行编辑、解析,时间一久觉得解析时按照固定的标签解析太过繁琐,作者决定通过反射搞一搞快速解析生成XML。

XML分析

XML的结构骨架其实很简单,就是标签的集合。所以我们需要定义出抽象的标签类来(作者的灵感来源是来自Android的View的设计模式)

XML标签基类

XML标签的结构:标签名、标签属性、子标签。
注意:例如:<Device name=""/>这里的标签名是Device。标签属性指的是name="",所以标签属性应该是key-value形式。子标签可能有可能没有,所以我们需要一种模式来将他们统一起来设计模式之组合模式

好,分析完了,下面来定义类

XMLAttribute - 标签的属性类

只有namevalue两个变量

public class XMLAttribute {
    private String name;//属性名
    private String values;//属性值
    //构造方法和getter、setter方法
}
XMLBase - 标签的基类

定义nameXMLAttributes两个变量,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标签我们按照有无子标签进行分类区别,分为XMLHasKidsXMLNoKids两种,下面分别实现。

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;
    }
  到此,需要用到的基础对象都已设计完成,下一篇记录解析过程的设计实现
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值