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

news/2024/5/19 2:26:51 标签: Android, JAVA, 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;
    }
  到此,需要用到的基础对象都已设计完成,下一篇记录解析过程的设计实现

http://www.niftyadmin.cn/n/1568410.html

相关文章

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

XMLParse之XML文件解析实现 第一篇已经介绍了基础的XMLAttribute、XMLBase、XMLNoChilds、XMLHasKids四个类的设计&#xff0c;接下来我们根据上面四个类进行XML文件的解析。 提示&#xff0c;在解析XML时用到了第三方的dom4j.jar导入即可&#xff08;站在巨人肩膀上真的很好&…

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

XMLParse之XML文件生成实现 前面实现了XML的设计和文件解析&#xff0c;对于XML文件的生成&#xff0c;原理依然是按照反射机制&#xff0c;将XML标签类实例逆向保存到dom4j.jar中的Element中&#xff0c;对照前面两篇文章&#xff0c;实现并不困难 思路分析 通过反射取到XML标…

Android NDK基本配置

Windows下Android ndk 配置 ndk包 本次安装用的是android ndk 版本为 android-ndk-r12b-windows-x86_64 环境变量配置 将解压后的ndk路径添加到PATH中&#xff0c;本机为“D:/ndk” Android项目配置 1.新建Android项目,local.properties加入ndk.dirD:\ndk 2.完成后&…

Activity的四种加载模式

在多Activity开发中&#xff0c;有可能是自己应用之间的Activity跳转&#xff0c;或者夹带其他应用的可复用Activity。可能会希望跳转到原来某个Activity实例&#xff0c;而不是产生大量重复的Activity。这需要为Activity配置特定的加载模式&#xff0c;而不是使用默认的加载模…

PathMeasure 重点方法详解(文章有错,待校正)

PathMeasure 重点方法详解 前 最近准备系统学习一下Android知识&#xff0c;Path操作时遇到一个比较难理解的类PathMeasure,一番研究&#xff08;百度一下&#xff09;&#xff0c;记录一下自己的理解。在此特别感谢GcsSloop同学的博文&#xff0c;对于 Android 自定义 view 知…

PendingIntent学习小结

近日为解决android闹钟标签问题&#xff0c;分析了android的DeskClock应用&#xff0c;发现在AlarmReceiver.java类中用PendingIntent封装的Intent&#xff0c;通过putExtra存入alarm值&#xff0c;当标签重新设定时在当前类中值相应发生了改变&#xff0c;然而当通过intent启动…

GreenDao笔记(一)

最近在搜寻好的数据库操作框架&#xff0c;发现GreenDao确实不错&#xff0c;结合项目使用过程&#xff0c;记录下配置细节&#xff0c;以供随时查看 GreenDao 数据库配置 greenDao不做太多介绍&#xff0c;一个很厉害的数据库框架&#xff0c;每秒钟读写高达30000次&#xff…

Android开发中进程等级相关

Android五个进程等级 1、前台进程&#xff08;Foreground process&#xff09;&#xff1a;   用户当前工作所需要的。一个进程如果满足下列任何条件被认为是前台进程&#xff1a; 正运行着一个正在与用户交互的活动&#xff08;Activity对象的onResume()方法已经被调用&…