基于Pull和Java反射的XML解析

基本原理

  1. 使用反射,获取对象的属性名。
  2. 使用Pull解析XML,遇到节点与属性名相同,则赋值到该属性上。

简单暴力地贴代码

解析单个对象

    /**
     * 将XML流,反序列化成对象实例
     * @param xmlInputStream XML流
     * @param cls 反序列化对象的Class对象
     * @param  反序列化对象
     * @return 反序列结果
     */
    public static  T xmlToSingleObj(InputStream xmlInputStream, Class cls) {

        // 数据源为空,目标类型为空,不处理
        if (xmlInputStream == null || cls == null)
            return null;

        // 获取反序列对象的属性,无属性,不执行解析
        Field[] objFields = cls.getDeclaredFields();
        if (objFields == null || objFields.length == 0) {
            closeInputStream(xmlInputStream);
            return null;
        }

        // 开始解析
        try {

            // 声明结果对象
            T obj = null;

            // 构建解析器
            XmlPullParser mParser = Xml.newPullParser();
            mParser.setInput(xmlInputStream, "UTF-8");

            // 循环处理解析事件,直至XML结束
            while (mParser.getEventType() != XmlPullParser.END_DOCUMENT) {
                switch (mParser.getEventType()) {

                    // 文档开始,实例化结果对象
                    case XmlPullParser.START_DOCUMENT:
                        obj = cls.newInstance();
                        break;

                    // 解析到标签,获取标签名,匹配是否有相同的属性名(忽略大小写),有则赋值
                    case XmlPullParser.START_TAG:
                        String name = mParser.getName();
                        for (Field field : objFields) {
                            if (field.getName().equalsIgnoreCase(name)) {
                                field.setAccessible(true);
                                field.set(obj, mParser.nextText());
                                break;
                            }
                        }
                        break;

                    default:
                        break;
                }

                // 执行下一个事件
                mParser.next();
            }
            closeInputStream(xmlInputStream);
            return obj;
        } catch (Exception e) {
            closeInputStream(xmlInputStream);
            e.printStackTrace();
            Log.e(TAG, "XiaXmlParser.xmlToSingleObj()执行出错");
            Log.e(TAG, e.toString());
            return null;
        }
    }

解析列表


    /**
     * 将XML字符,反序列化成列表对象实例
     * @param xmlInputStream XML输入流
     * @param cls 反序列化对象的Class对象
     * @param childName 列表节点名称
     * @param  反序列化对象
     * @return 解析结果
     */
    public static  List xmlToListObj(InputStream xmlInputStream, Class cls, String childName) {

        // 数据源,目标类型,列表节点名称为空,不处理
        if (xmlInputStream == null || cls == null || TextUtils.isEmpty(childName)) {
            return null;
        }

        // 获取反序列对象的属性,无属性,不执行解析
        Field[] objFields = cls.getDeclaredFields();
        if (objFields == null || objFields.length == 0) {
            closeInputStream(xmlInputStream);
            return null;
        }

        // 开始解析
        try {

            // 声明结果对象
            List datas = null;
            T obj = null;

            // 构建解析器
            XmlPullParser mParser = Xml.newPullParser();
            mParser.setInput(xmlInputStream, "UTF-8");

            // 循环处理解析事件,直至XML结束
            while (mParser.getEventType() != XmlPullParser.END_DOCUMENT) {
                switch (mParser.getEventType()) {

                    // 文档开始,实例化结果对象
                    case XmlPullParser.START_DOCUMENT:
                        datas = new ArrayList<>();
                        break;

                    // 解析到开始标签,获取标签名
                    case XmlPullParser.START_TAG:
                        String name = mParser.getName();

                        // 若是元素节点,创建元素
                        if (name.equalsIgnoreCase(childName)) {
                            obj = cls.newInstance();
                            break;
                        }

                        // 匹配是否有相同的属性名(忽略大小写),有则赋值
                        for (Field field : objFields) {
                            if (field.getName().equalsIgnoreCase(name)) {
                                field.setAccessible(true);
                                field.set(obj, mParser.nextText());
                                break;
                            }
                        }
                        break;

                    // 解析到结束标签,获取标签名
                    case XmlPullParser.END_TAG:
                        String endTag = mParser.getName();

                        // 若是元素节点,结束当前元素的解析,放入列表
                        if (endTag.equalsIgnoreCase(childName) && datas != null && obj != null) {
                            datas.add(obj);
                        }
                        break;

                    default:
                        break;
                }

                // 执行下一个事件
                mParser.next();
            }
            closeInputStream(xmlInputStream);
            return datas;
        } catch (Exception e) {
            closeInputStream(xmlInputStream);
            e.printStackTrace();
            Log.e(TAG, "XiaXmlParser.xmlToListObj()执行出错");
            Log.e(TAG, e.toString());
            return null;
        }
    }

测试数据

public class DemoBean {

    private String name;
    private String age;
    private String sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public final static String TEST_DATA =
            "" +
            "   xia" +
            "   18" +
            "   " +
            "";


    public final static String TEST_DATA_LIST =
            "" +
            "   " +
            "       xia" +
            "       18" +
            "       " +
            "   " +
            "   " +
            "       wei" +
            "       19" +
            "       " +
            "   " +
            "   " +
            "       yao" +
            "       20" +
            "       " +
            "   " +
            "";
}

使用

    DemoBean mDemoBean = XiaXmlParser.xmlToSingleObje(DemoBean.TEST_DATA, DemoBean.class);
    List mDemoBeans = XiaXmlParser.xmlToListObj(DemoBean.TEST_DATA_LIST, DemoBean.class, "DemoBean");

代码完全体

点击这里 进行时空跳转

最后

  1. 只是DEMO,用于理解Pull解析和Java反射技术。
  2. 只支持属性的类型是String,需要支持更多类型,发挥你们的小宇宙吧。(/笑脸

你可能感兴趣的:(基于Pull和Java反射的XML解析)