Android SAX解析XML

SAX(simpleAPIforXML)是一种XML解析的替代方法。相比于DOM,SAX是一种速度更快,更有效的方法。它逐行扫描文档,一边扫描一边解析。而且相比于DOM,SAX可以在解析文档的任意时刻停止解析,但任何事物都有其相反的一面,对于SAX来说就是操作复杂。

        SAX解析XML文档采用事件驱动模式。什么是事件驱动模式?它将XML文档转换成一系列的事件,由单独的事件处理器来决定如何处理。

       基于事件驱动的处理模式主要是基于事件源和事件处理器(或者叫监听器)来工作的。一个可以产生事件的对象叫做事件源,而一个可以针对事件作出响应的对象就被叫做事件处理器。

    SAX技术在处理XMl文件时并不一次性把XML文件装入内存,而是一边读一边解析。因此,这就需要处理如下5个分析点,也可称为分析事件。

  •     开始分析XML文件。该分析点表示SAX引擎刚开始处理XML文件,还没有读取XML文件中的内容。该分析点对应于DefaultHandler类中的startDocument事件方法。可以在该方法中做一些初始化的工作。
  • 开始处理每一个XML元素,也就是遇到<product>、<item>这样的起始标记。SAX引擎每次扫描到新的XML元素的其实标记时会触发这个分析事件,对应的事件方法是startElement。在该方法中可以获得当前元素的名称,元素属性的相关信息。
  • 处理完一个XML元素,也就是遇到</product>、</item>这样的结束标记。该分析点对应的事件方法是endElement。在该事件中可以获得当前处理完的元素的全部信息。
  • 处理完XML文件。如果SAX引擎将整个XML文件的内容都扫描完了就到了这个分析点,该分析点对应的事件方法是endDocument。该事件方法可能不是必需的,如果最后有一些收尾工作,如释放一些资源,可以在该方法中完成。
  • 读取字符分析点。这是最重要的分析点。如果没有这个分析点,前4步的处理相当于白跑了一遍,虽然读取了XML文件中的所有内容,但并未保存这些内容。而这个分析点所对应的characters事件方法的主要作用就是保存SAX引擎读取的XMl文件中的内容。更准确地说是保存XML元素的文本,也就是<product>abc</product>中的abc.
在SAX接口中,事件源是org.xml.sax包中的XMLReader,他通过parse()方法开始解析XML文档,并根据文档内容产生事件。而事件处理器则是org.xml.sax包中的ContentHandler、DTDHandler、ErrorHandler,以及EntityResolver这四个接口。他们分别处理事件源在解析过程中产生不同类的事件(其中DTDHandler为解析文档DTD时所用)。详细介绍如下表:  

XML文件:
<?xml version="1.0" encoding="utf-8"?>
<products>
    <product>
        <id>10</id>
        <name>电脑</name>
        <price>2067.25</price>
    </product>
    <product>
        <id>20</id>
        <name>微波炉</name>
        <price>520</price>
    </product>
</products>

Product类的代码:
package com.sax.xml;

public class Product {
	private int id;
	private String name;
	private float price;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public float getPrice() {
		return price;
	}

	public void setPrice(float price) {
		this.price = price;
	}

}

上面XML文件<product>标签中的3个子标签的值与Product类的3个属性对应。
SAXParseXML解析类,该类是DefaultHandler的子类,代码如下:
package com.sax.xml;

import java.util.ArrayList;
import java.util.List;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class SAXParseXML extends DefaultHandler {
	private List<Product> products;
	private Product product;
	private StringBuffer buffer = new StringBuffer();

	public List<Product> getProducts() {
		return products;
	}

	@Override
	public void startDocument() throws SAXException {
		products = new ArrayList<Product>();
		super.startDocument();
	}

	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		if (localName.equals("product")) {
			product = new Product();
		}
		super.startElement(uri, localName, qName, attributes);
	}

	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		if (localName.equals("product")) {
			products.add(product);
		}else if (localName.equals("id")) {
			product.setId(Integer.parseInt(buffer.toString().trim()));
			buffer.setLength(0);
		}else if (localName.equals("name")) {
			product.setName(buffer.toString().trim());
			
		}else if (localName.equals("price")) {
			product.setPrice(Float.parseFloat(buffer.toString().trim()));
			buffer.setLength(0);
		}
		super.endElement(uri, localName, qName);
	}

	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		buffer.append(ch, start, length);
		super.characters(ch, start, length);
	}
	
}

  • startDocument:第一个分析点 事件方法。在该方法中创建了用于保存转换结果的List<Product>对象。
  • startElement:第二个分析点事件方法。SAX引擎分析到每一个<product>元素时,在该方法中都创建一个Product对象。
  • endElement: 第三个分析点事件方法。该方法中的代码最复杂,但仔细看一下,其实很简单。当SAX引擎分析完每一个XML元素后,会将该元素中的文本保存在Product对象的响应属性中。
  • endDocument:第四个分析点事件方法。在该方法中什么都没有做,也没有覆盖这个方法。
  • characters:第五个分析点事件方法。虽然该方法中的代码有开发人员编写的只有一行,但十分关键。在该方法中将SAX引擎扫描到的内容保存在buffer变量中。而在endElement方法中要使用该变量中的内容为Product对象中的属相赋值。
最后去调用这个解析类:

package com.sax.xml;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.List;

import com.sax.xml.Product;
import com.sax.xml.SAXParseXML;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.util.Xml;

public class Main extends Activity{

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		try {
			FileInputStream fis = new FileInputStream("/mnt/sdcard/product.xml");
			SAXParseXML saxParseXML = new SAXParseXML();
			android.util.Xml.parse(fis, Xml.Encoding.UTF_8, saxParseXML);
			List<Product> products = saxParseXML.getProducts();
			System.out.println("共"+products.size()+"个产品");
			for (Product product : products) {
				System.out.println("id: "+product.getId()+" 产品名: "+product.getName()+" 价格: "+product.getPrice());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

结果如下:
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值