Android XML数据解析——SAX解析

本文介绍了Android中解析XML的三种方式,重点讲解了SAX解析技术。SAX解析器以事件驱动的方式处理XML,具有速度快、内存占用少的优点,特别适合于移动设备。通过创建继承自DefaultHandler的类并复写相关方法,可以从服务器获取XML数据并进行解析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

XML称为可扩展标记语言,它与HTML一样,都是SGML(标准通用标记语言),XML是Internet环境中跨平台的,依赖于内容技术,是当前处理结构化文档信息的有力工具,可扩展标记语言XML是一种简单的数据存储语言,使用一些列简单的标记描述数据。

XML结构示意图:

<?xml version = "1.0" encoding = "UTF-8"?>
<persons>
	<person id ="23">
		<name> jack</name>
 		<age>30</age>	
 	</person>
	<person id = "20">
		<name>rose</name>
 		<age>25</age>
</persons>
XML的结构解析如下:
1、节点
2、元素
3、属性和属性值
由于XML的扩展性强,致使它需要有稳定的基础规则来支持扩展,该语法的规则是:
1、开始和结束标签匹配
2、嵌套标签不能互相嵌套
3、区分大小写

Android中,解析XML数据的三种方式:
1、DOM
“文档对象模型”方式,解析完的XML将生成一个树状结构的对象

2、SAX
simple APIforXML,以事件的形式通知程序,对XML进行解析

3、PULL
类似于SAX方式,程序以“拉取”的方式对XML进行解析

SAX技术介绍:
由它定义的事件流可以指定从解析器传到专门的处理程序的代码的XML结构,简单的讲,它解析速度快,占用内存少的解析器,这种解析器比较适合android 等移动设备。
优点:
因为SAX的优势是流的方式处理,当遇到一个标签的时候,并不会记录下当前所碰到的标签,也就是说在startElement方法中,你所知道的信息,仅仅是当前的签名的名字和属性,至于标签的嵌套结构,上层标签的名字,是否有子元素与其他结构相关的信息,都是不知道的。

/*=========解析XML文件标准流程==========
 * 1、声明一个类,继承defaultHandle类,复写对应的方法
 * 2、声明一个HttpUtil的类,从服务器端取回输入流
 * 3、编写一个业务流程的方法,创建一个解析工厂

第一步:声明一个类,复写方法

//defaultHanler这个类是专门用来Sax解析用的
public class MyHandler 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 MyHandler(String nodeName) {
		this.nodeName = nodeName;
	}


	public List<HashMap<String, String>> getList() {
		return list;
	}
	
	
	//开始解析文档,当读到第一个开始标签的时候,会触发这个方法
	public void startDocument() throws SAXException {
		// TODO 自动生成的方法存根
		list = new ArrayList<HashMap<String, String>>();
		
		super.startDocument();
	}
	
	//开始解析节点,当遇到文档的开头的时候,调用此方法
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		if(qName.equals(nodeName)){
			map = new HashMap<String, String>();
		}
		if(attributes !=null && map !=null){
			//把当前节点的属性值取出来
			for(int i = 0; i<attributes.getLength(); i++){
				map.put(attributes.getQName(i), attributes.getValue(i));
			}
		}
		currentTag = qName;
	}// 执行完这一步之后,<person  id = "23">这一行就解析结束了
	
	//报存节点内容,这个方法是用来处理XML文件所读取到的内容
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		if(currentTag !=null && map!=null){
			currentValue = new String(ch,start, length);
			//执行完这句就相当于把<name>jack</name>解析完
			if(currentValue !=null && !currentValue.trim().equals("") && !currentValue.trim().equals("\n")){
				map.put(currentTag, currentValue);
			}
		}
		currentTag = null;
		currentValue = null;
		/*为什么需要设置为空呢,例如解析
		 * <name> jack</name>
		 * <age>30</age> 当解析完<name >之后,到下一行开始解析<age>,需要重新把当前节点的对应值和标签设置为空
		 * */
	}

	//遇到结束标记的时候会调用这个方法
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		if(qName.equals(nodeName)){
			list.add(map);
			map = null;
		}
		/*表示当前这个节点已经解析完了,需要解析下一个节点
		 * 例如:<person id = "23"> 
		 * 	 	  …………
		 * 	</person>
		 * 	<person id = "20">
		 * 		   …………
		 * 	</person>
		 * 意思就是person id = "23"这个节点已经解析完了,需要解析id = “20”这个新节点 
		 * */
	}
}

第二步:声明一个HttpUtil的类,从服务器端取回数据

public class httpUtils {
	public httpUtils() {
		// TODO 自动生成的构造函数存根
	}
	
	public static InputStream getXML(String path){
		InputStream inputStream = null;
		try {
			URL url = new URL(path);
			if(url != null){
				HttpURLConnection connection = (HttpURLConnection) url.openConnection();
				connection.setConnectTimeout(3000);
				connection.setDoInput(true);
				connection.setRequestMethod("GET");
				int code = connection.getResponseCode();
				if(code == 200){
					inputStream = connection.getInputStream();
				}
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
		return inputStream;
	}		
}

第三步:创建解析工厂

public class saxService {
	public saxService() {
		// TODO 自动生成的构造函数存根
	}
	public static List<HashMap<String, String>> readXML(
			InputStream in, String nodeName){	
		try{
			//创建一个解析XML的工厂
			SAXParserFactory spf = SAXParserFactory.newInstance();
			SAXParser parser = spf.newSAXParser();
			MyHandler handler = new MyHandler(nodeName);
			parser.parse(in, handler);
			in.close();
			return handler.getList();
		} catch (Exception e){
		}
		return null;
	}
}

第四步:主方法中调用各类函数进行解析

public class Test {
	public Test() {
		// TODO 自动生成的构造函数存根
	}
	
	public static void main(String args[]){
		String path = "http://192.168.0.102:8080/myHttp/person";
		//从服务器端获得流
		InputStream inputStream = httpUtils.getXML(path);
		try {
			List<HashMap<String, String>> list = saxService.readXML(inputStream, "person");
			for(HashMap<String, String> map :list){
				System.out.println(map.toString());
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
}
输出结果如下:

{id = 23, name = jack, age = 30}

{id = 20, name = rose, age = 25}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值