Android解析XML三种方式

三种方式分别为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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值