Android使用Dom与SAX解析XML文件支持任意对象的读

25 篇文章 0 订阅


本工具类:主要运用到了java的反射来解析泛型的属性,并根据泛型属性来设置对象属性值,如果这点弄很熟悉的话,对于类似这种小框架的话应该都不成问题,


我的上一编文章没使用反射与泛型,各位大神可以比较下,哪种方式的灵活度

不使用反射与泛型


一.使用dom方式:

package com.example.lxb.mircoxml.xml;

import com.example.lxb.mircoxml.AppContext;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

/**
 * Created by lxb on 2017/4/27.
 */

public class XmlByDom<T> {

    /**
     * T t :为生返回的对象
     * <p>
     * <Volbook>
     * <p>
     * <Item>           通常解析从这个结点开始
     * <ID>0</ID>
     * <type>1</type>
     * <key>518</key>
     * <cmd>no</cmd>
     * </Item>
     * </Volbook>
     *
     * @param path
     * @return
     */
    public List<T> parseXMLByDom(String path, T t) {

        InputStream is = null;
        try {
            is = AppContext.getInstance().getAssets().open(path);

            Field[] fields = t.getClass().getDeclaredFields();      // 获得实例的属性,顺序并不会保证有序


            Map<String, Field> fieldList = FieldUtils.buildFiledList(fields);


            Method setmeth;                // 实例的set方法

            List<T> s = new ArrayList<>();

            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();


            Document doc = builder.parse(is);
            Element rootElement = doc.getDocumentElement();
            String secondNode = t.getClass().getSimpleName();       //二级结点作为解析开始的结点
            NodeList items = rootElement.getElementsByTagName(secondNode);


            /**
             * 每遍历一次解析的结点,需要实例一个对象
             */

            for (int i = 0; i < items.getLength(); i++) {

                t = (T) t.getClass().newInstance();                     // 获得对象的新的实例

                Node item = items.item(i);

                NodeList properties = item.getChildNodes();

                for (int j = 0; j < properties.getLength(); j++) {

                    Node property = properties.item(j);

                    if (property instanceof Element) {


                        String nodeName = property.getNodeName();

                        /**
                         * 这里主要,处理 反射获取 属性无序的情况
                         */
                        String method = "set" + nodeName.substring(0, 1).toUpperCase() + nodeName.substring(1);

                        setmeth = t.getClass().getMethod(method, fieldList.get(nodeName).getType());

                        //System.out.println("95--------" + fieldList.get(nodeName).getType().toString());

                        if(fieldList.get(nodeName).getType().toString().equals("int")){

                            setmeth.invoke(t, Integer.parseInt(property.getFirstChild().getNodeValue()));

                        }else if(fieldList.get(nodeName).getType().toString().equals("boolean")){

                            setmeth.invoke(t, Boolean.parseBoolean(property.getFirstChild().getNodeValue()));
                        }
                        else{
                            setmeth.invoke(t, property.getFirstChild().getNodeValue());
                        }

                    }


                }
                s.add(t);
            }

            return s;

        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }


        return null;

    }

}

2.使用SAX方式:

package com.example.lxb.mircoxml.xml;


import com.example.lxb.mircoxml.AppContext;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

/**
 * 使用Sax解析xml文档
 * <p>
 * Created by lxb on 2017/4/26.
 */

public class ParseXMLSAX<T> {

    private static ParseXMLSAX parseXMLSAX;

    public static ParseXMLSAX getInstance() {

        if (parseXMLSAX == null) {

            parseXMLSAX = new ParseXMLSAX();
        }
        return parseXMLSAX;
    }

    /**
     * 获取assets文件
     *
     * @param path
     * @return
     */
    public InputStream getFileInputStream(String path) {

        try {

            return AppContext.getInstance().getAssets().open(path);

        } catch (IOException e) {

            e.printStackTrace();
        }

        return null;
    }

    /**
     * 解析xml文档
     *
     * @param path
     * @return
     * @throws Exception
     */
    public List<T> parse(String path, T t) throws Exception {

        InputStream is = getFileInputStream(path);

        SAXParserFactory factory = SAXParserFactory.newInstance();

        SAXParser parser = factory.newSAXParser();

        SaxXmlHandler<T> handler = new SaxXmlHandler<>(t);

        parser.parse(is, handler);

        return handler.getvoiceEntitys();
    }

    /**
     * DefaultHandler是一个事件处理器,可以接收解析器报告的所有事件,处理所发现的数据
     */
    private class SaxXmlHandler<T> extends DefaultHandler {

        private List<T> voiceEntitys;
        private T second;
        private StringBuilder builder;
        private Field[] fields;
        private String secondNode;
        private Method setMethod;                // 实例的set方法
        private  Map<String, Field> fieldList;


        public List<T> getvoiceEntitys() {
            return voiceEntitys;
        }

        public SaxXmlHandler(T t) {

            this.second = t;
        }


        @Override
        public void startDocument() throws SAXException {
            // TODO Auto-generated method stub
            super.startDocument();
            voiceEntitys = new ArrayList<>();
            builder = new StringBuilder();
            fields = this.second.getClass().getDeclaredFields();      // 获得实例的属性,顺序并不会保证有序
            fieldList = FieldUtils.buildFiledList(fields);
            secondNode = this.second.getClass().getSimpleName();
        }

        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            // TODO Auto-generated method stub
            super.startElement(uri, localName, qName, attributes);

            if (localName.equals(secondNode)) {     //在开始解析的结点处先new一个实例

                try {
                    second = (T) this.second.getClass().newInstance();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }

            builder.setLength(0);
        }

        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            // TODO Auto-generated method stub
            super.characters(ch, start, length);
            builder.append(ch, start, length);                  //将读取的字符数组追加到builder        }

        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            // TODO Auto-generated method stub
            super.endElement(uri, localName, qName);

            try {

                if(fieldList.containsKey(localName)){

                    String method = "set" + localName.substring(0, 1).toUpperCase() + localName.substring(1);
                    setMethod =  this.second.getClass().getMethod(method, fieldList.get(localName).getType());

                    if(fieldList.get(localName).getType().toString().equals("int")){

                        setMethod.invoke(this.second, Integer.parseInt(builder.toString()));

                    }else if(fieldList.get(localName).getType().toString().equals("boolean")){

                        setMethod.invoke(this.second, Boolean.parseBoolean(builder.toString()));
                    }
                    else{
                        setMethod.invoke(this.second, builder.toString());
                    }
                }
                if(localName.equals(secondNode)){       //说明第一层结点解析结束

                    voiceEntitys.add(this.second);
                }

            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }

        }

    }
}

3.工具类:

package com.example.lxb.mircoxml.xml;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by lxb on 2017/4/28.
 */

public class FieldUtils {

    public static  Map<String, Field> buildFiledList(Field[] fields) {

        Map<String, Field> fieldList = new HashMap<>();

        for (int i = 0; i < fields.length; i++) {

            String key = fields[i].toString().substring(fields[i].toString().lastIndexOf(".") + 1, fields[i].toString().length());

            fieldList.put(key, fields[i]);
        }

        return fieldList;

    }
}

4.与xml文件对应的实体类:

package com.example.lxb.mircoxml.model;

/**
 * Created by lxb on 2017/4/27.
 */

public class Item {



    private int ID;

    private String type;

    private String key;

    private String cmd;

    private boolean b;



    public int getID() {
        return ID;
    }

    public void setID(int ID) {
        this.ID = ID;
    }



    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }


    public String getCmd() {
        return cmd;
    }

    public void setCmd(String cmd) {
        this.cmd = cmd;
    }


    public void setB(boolean b){

        this.b = b;
    }

    public boolean getB(){
        return this.b;
    }



}

xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<volbook>

    <!-- 音量加 -->
    <Item>

        <ID>0</ID>
        <type>1</type>
        <key>518</key>
        <cmd>ywrtwer</cmd>
        <b>true</b>
    </Item>

    <!-- 音量减 -->
    <Item>

        <ID>1</ID>

        <type>1</type>
        <key>517</key>
        <cmd>no</cmd>

        <b>true</b>
    </Item>

    <!-- 亮度加 -->
    <Item>

        <ID>2</ID>

        <type>1</type>
        <key>520</key>
        <cmd>刘胡来</cmd>

        <b>true</b>
    </Item>




</volbook>  


6.测试代码:

private void readDom(){

  /*  XmlByDom<Item> dom = new XmlByDom<>();
    List<Item> tt = dom.parseXMLByDom("123.xml",new Item());*/


    ParseXMLSAX<Item> dom = new ParseXMLSAX<>();
    List<Item> tt = null;
    try {
        tt = dom.parse("123.xml",new Item());
    } catch (Exception e) {
        e.printStackTrace();
    }

    System.out.println("62------------------id :"+tt.get(0).getID() + "  type:" + tt.get(0).getType()
            + " key:" + tt.get(0).getKey() + " cmd:" +tt.get(0).getCmd() + " b: "+tt.get(0).getB());
}

可以仿造这种方式将任意对象写到xml文件中去


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值