您的位置:首页 > 移动开发 > Android开发

Android解析XML三种方式

2015-11-25 15:52 363 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/u011247160/article/details/50038275

三种方式分别为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节点层级较多时,效率会比前两者略低。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: