Android解析XML三种方式

来源:互联网 发布:mac下win 10安装重启 编辑:程序博客网 时间:2024/04/29 20:32

三种方式分别为SAX、PULL和DOM

先准备封装数据的类与http工具类

package com.lee.testxml1116.bean;/** * 存储person数据的bean类 * @author Lee * */public class Person {    private int id;    private int age;    private String name;        public Person() {        // TODO Auto-generated constructor stub    }    public Person(int id, int age, String name) {        super();        this.id = id;        this.age = age;        this.name = name;    }    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    @Override    public String toString() {        return "Person [id=" + id + ", age=" + age + ", name=" + name + "]";    }   }
package com.lee.testxml1116.utils;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;public class HttpUtil {    public HttpUtil() {        // TODO Auto-generated constructor stub    }    /**     * 获取http输入字节流,通过流获取服务器端返回的数据     * @param path     * @return     */    public static InputStream getXML(String path){        InputStream is = null;        try {            URL url = new URL(path);            if(null != url){                // 创建http连接                HttpURLConnection connection = (HttpURLConnection) url.openConnection();                // 设置连接超时时间为3秒                connection.setConnectTimeout(3000);                connection.setDoInput(true);                // 设置请求方式为get                connection.setRequestMethod("GET");                // 获取服务器响应状态码                int code = connection.getResponseCode();                // 若状态码为200(即正常),获取输入流                if(200 == code)                    is = connection.getInputStream();            }        } catch (Exception e) {            // TODO: handle exception        }        return is;    }}

一、SAX方式
用到org.xml.sax.helpers.DefaultHandler,所以要定义自己的handler类,重写读取xml文件的相关方法

package com.lee.testxml1116.utils;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import org.xml.sax.Attributes;import org.xml.sax.SAXException;import org.xml.sax.helpers.DefaultHandler;public class MySaxHandler extends DefaultHandler {    private HashMap<String,String> map = null;    private List<HashMap<String,String>> list = null;    private String currentTag = null;   // 当前解析的元素(节点)或属性的名字    private String currentValue = null; // 当前解析的元素(节点)或元素中属性的值    private String nodeName = null;     // 要解析的根元素(节点)的名字    public MySaxHandler(String nodeName) {        super();        // TODO Auto-generated constructor stub        this.nodeName = nodeName;    }       public List<HashMap<String, String>> getList() {        return list;    }    /**     * 读到文档开始时调用的方法     */    @Override    public void startDocument() throws SAXException {        list = new ArrayList<HashMap<String,String>>();    }    /**     * 读到某一元素(节点)开始时调用的方法     */    @Override    public void startElement(String uri, String localName, String qName,            Attributes attributes) throws SAXException {        // 判断当前元素(节点)是否为要解析的根元素(节点),如果是,则创建存储解析对象信息的map        System.out.println(qName);        if(nodeName.equals(qName)){            map = new HashMap<String, String>();        }        System.out.println(map);        // 判断该元素是否有标签内属性,有则存入map        if(!(null == attributes || null == map)){            for(int i = 0;i < attributes.getLength();i++){                System.out.println(attributes.getQName(i));                map.put(attributes.getQName(i), attributes.getValue(i));            }        }        currentTag = qName;    }    /**     * 读到元素(节点)中字符类型数据时调用的方法     */    @Override    public void characters(char[] ch, int start, int length)            throws SAXException {        // 判断当前元素(节点)名称是否为空,不为空,则取值        if(!(null == map || null == currentTag)){            currentValue = new String(ch, start, length);            // 判断当前值是否为空、是否等于换行符,两者均否,则存入map            if(!(null == currentValue || "".equals(currentValue.trim()) || "\n".equals(currentValue.trim()))){                map.put(currentTag, currentValue);            }        }        // 存储数据结束后,将currentTag与currentValue初始化        currentTag = null;        currentValue = null;    }    /**     * 读到元素(节点)结束标记时调用的方法     */    @Override    public void endElement(String uri, String localName, String qName)            throws SAXException {        // 判断当前结束标记是否为目标根节点,若是,则将map存入list中        if(qName.equals(nodeName)){            list.add(map);            // 将map初始化            map = null;        }    }    /**     * 读到文档结束时调用的方法     */    @Override    public void endDocument() throws SAXException {        //     }}

定义完handler之后,创建一个service类,来封装从xml中获取数据的方法

package com.lee.testxml1116.service;import java.io.InputStream;import java.util.HashMap;import java.util.List;import javax.xml.parsers.SAXParser;import javax.xml.parsers.SAXParserFactory;import com.lee.testxml1116.utils.MySaxHandler;/** * 以SAX方式解析xml并返回数据的服务类 * @author Lee * */public class SaxService {    public SaxService() {        // TODO Auto-generated constructor stub    }    public static List<HashMap<String,String>> readXML(InputStream is, String nodeName){        try {            // 创建SAX解析工厂,获取一个解析对象            SAXParserFactory spf = SAXParserFactory.newInstance();            SAXParser parser = spf.newSAXParser();            // 创建一个自定义DefaultHandler对象            MySaxHandler handler = new MySaxHandler(nodeName);            // 解析xml            parser.parse(is, handler);            // 关闭InputStream            if(null != is)                is.close();            // 返回存储数据的list集合            return handler.getList();        } catch (Exception e) {            // TODO: handle exception        }        return null;    }}

二、Pull方式
当使用pull方式解析xml时,需要用到第三方包kxml,这里使用的是kxml2-2.2.2.jar
这里写图片描述

主要用到的类就是org.xmlpull.v1.XmlPullParser

package com.lee.testxml1116.utils;import java.io.IOException;import java.io.InputStream;import java.util.ArrayList;import java.util.List;import org.xmlpull.v1.XmlPullParser;import org.xmlpull.v1.XmlPullParserException;import org.xmlpull.v1.XmlPullParserFactory;import com.lee.testxml1116.bean.Person;/** * 以pull方式解析xml的工具类 * @author Lee * */public class PullXMLUtil {    public PullXMLUtil() {        // TODO Auto-generated constructor stub    }    public static List<Person> parseXML(InputStream is, String encode) throws XmlPullParserException, NumberFormatException, IOException{        List<Person> persons = null;        Person person = null;        XmlPullParserFactory factory = XmlPullParserFactory.newInstance();        XmlPullParser parser = factory.newPullParser();        parser.setInput(is, encode);        int eventType = parser.getEventType();        while(eventType != XmlPullParser.END_DOCUMENT){            switch (eventType) {            case XmlPullParser.START_DOCUMENT:                persons = new ArrayList<Person>();                break;            case XmlPullParser.START_TAG:                if("person".equals(parser.getName())){                    person = new Person();                    int id = Integer.parseInt(parser.getAttributeValue(0));                    person.setId(id);                } else if("age".equals(parser.getName())){                    int age = Integer.parseInt(parser.nextText());                    person.setAge(age);                } else if("name".equals(parser.getName())){                    String name = parser.nextText();                    person.setName(name);                }                break;            case XmlPullParser.END_TAG:                if("person".equals(parser.getName())){                    persons.add(person);                    person = null;                }                break;            }            eventType = parser.next();        }        return persons;    }}

三、DOM方式

package com.lee.testxml1116.utils;import java.io.IOException;import java.io.InputStream;import java.util.ArrayList;import java.util.List;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import javax.xml.parsers.ParserConfigurationException;import javax.xml.soap.Node;import org.w3c.dom.Document;import org.w3c.dom.Element;import org.w3c.dom.NodeList;import org.xml.sax.SAXException;import com.lee.testxml1116.bean.Person;/** * 以DOM方式解析xml的工具类 *  * @author Lee *  */public class DomXMLUtil {    public DomXMLUtil() {        // TODO Auto-generated constructor stub    }    /**     * 从在http连接中取到的流中读取xml数据     *      * @param is     * @return     * @throws ParserConfigurationException     * @throws IOException     * @throws SAXException     */    public static List<Person> readXML(InputStream is)            throws ParserConfigurationException, SAXException, IOException {        List<Person> persons = new ArrayList<Person>();        // 创建一个文档构造器工厂,用以获取文档构造器        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();        // 获取一个文档构造器的实例,用以获取文档        DocumentBuilder builder = dbf.newDocumentBuilder();        // 获取一个文档实例        Document document = builder.parse(is);        // 获取文档中的元素集合        Element element = document.getDocumentElement();        // 在元素集合中获取目标节点的集合        NodeList personNodes = element.getElementsByTagName("person");        // 遍历目标节点集合,解析xml        for (int i = 0; i < personNodes.getLength(); i++) {            // 获取当前的目标节点            Element personElement = (Element) personNodes.item(i);            Person person = new Person();            // 获取当前节点中属性的值,并给person对象赋值            person.setId(Integer.parseInt(personElement.getAttribute("id")));            // 获取当前节点下子节点的集合            NodeList childNodes = personElement.getChildNodes();            // 遍历子节点集合            for (int j = 0; j < childNodes.getLength(); j++) {                // 判断当前的节点类型是否为元素节点,若是,则解析取值、赋值                if(childNodes.item(j).getNodeType() == Node.ELEMENT_NODE){                    String nodeName = childNodes.item(j).getNodeName();                    String nodeValue = childNodes.item(j).getFirstChild().getNodeValue();                    if("name".equals(nodeName)){                        person.setName(nodeValue);                    } else if("age".equals(nodeName)){                        person.setAge(Integer.parseInt(nodeValue));                    }                }            }            // 子节点集合遍历结束后,即已经完成对一个person节点的解析,因此将一个完整的person对象存入list中            persons.add(person);        }        return persons;    }}

最后附上测试类,对这三种方式进行测试

package com.lee.testxml1116.test;import java.io.IOException;import java.io.InputStream;import java.util.List;import javax.xml.parsers.ParserConfigurationException;import org.xml.sax.SAXException;import org.xmlpull.v1.XmlPullParserException;import com.lee.testxml1116.bean.Person;import com.lee.testxml1116.utils.DomXMLUtil;import com.lee.testxml1116.utils.HttpUtil;import com.lee.testxml1116.utils.PullXMLUtil;/** * 测试类 * @author Lee * */public class Test {    public Test() {        // TODO Auto-generated constructor stub    }    /**     * @param args     */    public static void main(String[] args) {        // TODO Auto-generated method stub        String path = "目标xml文件的url地址";        InputStream is = HttpUtil.getXML(path);        /*         * 以SAX方式解析        List<HashMap<String,String>> list = SaxService.readXML(is, "person");        for(HashMap<String, String> map : list){            System.out.println(map.toString());        }        */        List<Person> persons = null;        /*         * 以pull方式解析        try {            persons = PullXMLUtil.parseXML(is, "UTF-8");            for(Person person : persons){                System.out.println(person.toString());            }        } catch (NumberFormatException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (XmlPullParserException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        */        // 以dom方式解析        try {            persons = DomXMLUtil.readXML(is);            for(Person person : persons){                System.out.println(person.toString());            }        } catch (ParserConfigurationException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (SAXException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }}

三种方法相比,由于dom使用的是循环嵌套,所以当xml节点层级较多时,效率会比前两者略低。

0 0
原创粉丝点击