java利用反射实现Sax实现 xml万能解析器

大概思路:
1.首先我们通过输入流来获取要读取的xml文件。
2xml是存放一个对象的数据源,具体对象中的属性我们不知道,那么我们就需要利用反射来读取对象中的属性,利用反射来创建对象,给对象赋值。
3.开始解析,执行开始文档的方法,<> 开始标签里面有值就可以利用attributes.getValue()方法来获取值.
4.读取到属性调用 characters()方法将属性存起来,到结束文档的方法
5结束解析,执行开始文档的方法</>就代表读完一个对象,将对象存入集合

1.提供返回数据源的方法

public  ArrayList saxReadXML(InputStream is,Class aClass) throws Exception {
    this.aClass=aClass;
    SAXParserFactory factory = SAXParserFactory.newInstance();//获得解析工厂
    SAXParser parser = factory.newSAXParser();//获得解析器
    parser.parse(is,new SaxHepler());//加载要解析的数据
    return list;
}

2.封装DefaultHandler解析类

class SaxHepler extends DefaultHandler{
    @Override
    public void startDocument() throws SAXException {
        super.startDocument();//文档开始
    }

    @Override
    public void endDocument() throws SAXException {
        super.endDocument();//文档结束
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        super.startElement(uri, localName, qName, attributes);
        /**
         * 获得这个类的名字转小写
         * 1.例:<sudent> 的这个对象是Student ,转成student
         */
        String name = aClass.getSimpleName().toLowerCase();
        if(qName.equals(name)){
            try {
                object= aClass.newInstance();//创建这个class对象
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            }
            Field[] declaredFields = aClass.getDeclaredFields();//获得这个class对象的字段
            for (int i=0;i<declaredFields.length;i++){
                //attributes 这个参数就是开始标签里的属性 例:<Student id="1" name="张三">
                for(int j=0;j<attributes.getLength();j++){
                    String name1 = declaredFields[i].getName();//获取这个标签名
                    String qName1 = attributes.getQName(j);//获取标签里的值
                    if(name1.equals(qName1)){
                        try {
                            declaredFields[i].set(object,attributes.getValue(j));//给这个对象设置值
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                }

            }

        }
    }
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        super.endElement(uri, localName, qName);
        String name = aClass.getSimpleName().toLowerCase();//同上
        Field[] declaredFields = aClass.getDeclaredFields();//获取这个对象里的属性
        if(qName.equals(name)){//如果判断结束了</student> 那么就将这个对象存入集合
            list.add(object);
        }
        for (int i=0;i<declaredFields.length;i++){//通过属性字段来遍历每一个属性
            String name1 = declaredFields[i].getName();//获得每个字段的属性名字
            if(qName.equals(name1)){
                try {
                    declaredFields[i].set(object,string);//设置值
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }

    }
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        super.characters(ch, start, length);
        string=new String(ch,start,length);//存起来
    }
}

3.使用的写法

River student=null;
try {
    InputStream open = getAssets().open("rivers.xml");
    ArrayList<River> arrayList = new SaxTool().saxReadXML(open, River.class);
    for(int i=0;i<arrayList.size();i++){
        student= arrayList.get(i);
        textView.append(student.toString()+"\n");
    }
}   catch (Exception e) {
    e.printStackTrace();
}

4.解析的XML文件

<?xml version="1.0" encoding="utf-8"?>
<rivers>
    <river name="灵渠" length="605">
        <introduction>
            灵渠在广西壮族自治区兴安县境内,是世界上最古老的运河之一,有着“世界古代水利建筑明珠”的美誉。灵渠古称秦凿渠、零渠、陡河、兴安运河,于公元前214年凿成通航,距今已2217年,仍然发挥着功用。
        </introduction>
        <imageurl>
            http://imgsrc.baidu.com/baike/pic/item/389aa8fdb7b8322e08244d3c.jpg
        </imageurl>
    </river>
    <river name="胶莱运河" length="200">
        <introduction>
            胶莱运河南起黄海灵山海口,北抵渤海三山岛,流经现胶南、胶州、平度、高密、昌邑和莱州等,全长200公里,流域面积达5400平方公里,南北贯穿山东半岛,沟通黄渤两海。胶莱运河自平度姚家村东的分水岭南北分流。南流由麻湾口入胶州湾,为南胶莱河,长30公里。北流由海仓口入莱州湾,为北胶莱河,长100余公里。
        </introduction>
        <imageurl>
            http://imgsrc.baidu.com/baike/pic/item/389aa8fdb7b8322e08244d3c.jpg
        </imageurl>
    </river>
    <river name="苏北灌溉总渠" length="168">
        <introduction>
            位于淮河下游江苏省北部,西起洪泽湖边的高良涧,流经洪泽,青浦、淮安,阜宁、射阳,滨海等六县(区),东至扁担港口入海的大型人工河道。全长168km。
        </introduction>
        <imageurl>
            http://imgsrc.baidu.com/baike/pic/item/389aa8fdb7b8322e08244d3c.jpg
        </imageurl>
    </river>
</rivers>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值