Android简化xml sax解析
dom解析占用内存大(我这边需要解析各种各样的kml文件,有时4-5M的kml文件使用dom解析很多手机就内存溢出了),也需要引入第三方库,所以使用相对于节省内存很多、不需引入其他库的sax解析就是很好的选择了。因为sax解析比较复杂的xml文件特别麻烦,所以整理了一个简化android sax解析的工具。
实现思路:和Android Touch事件传递机制一样,把需要子解析器解析的节点往下传递。
如果有进一步简化的方法,欢迎交流!email:csqwyyx@163.com。
示例程序:https://github.com/John-Chen/EasySaxParser
简化工具SaxParser:
public abstract class SaxParser {
protected String curQName;
protected StringBuilder curValue = new StringBuilder();
protected SaxParser saxParser;
protected String saxParserQName;
/**
* 需要生成子SaxParser的节点名称
*/
protected HashSet<String> childParserQNames;
public SaxParser() {
}
public SaxParser(HashSet<String> childParserQNames) {
this.childParserQNames = childParserQNames;
}
protected void startElement(String uri, String localName, String qName, Attributes attributes) {
if(qName == null){
return;
}
if(saxParser != null){
saxParser.startElement(uri, qName, qName, attributes);
}else if(childParserQNames != null && childParserQNames.contains(qName)){
this.saxParser = dispatchTo(qName, attributes);
if(this.saxParser != null){
this.saxParserQName = qName;
saxParser.parserStart(attributes);
}
}else{
curQName = qName;
if(curValue.length() > 0){
curValue.delete(0, curValue.length());
}
}
}
protected void endElement(String uri, String localName, String qName) {
if(qName == null){
return;
}
if(qName.equals(saxParserQName)){
if(saxParser != null){
saxParser.parserEnd();
}
saxParser = null;
saxParserQName = null;
}else if(saxParser != null){
saxParser.endElement(uri, qName, qName);
}else{
parserElementEnd(qName, curValue.toString());
curQName = null;
if(curValue.length() > 0){
curValue.delete(0, curValue.length());
}
}
}
protected void characters(char[] ch, int start, int length) {
if(saxParser != null){
saxParser.characters(ch, start, length);
}else{
String data = new String(ch, start, length);
if(data.length() > 0 && curQName != null){
curValue.append(data);
}
}
}
/**
* 开始解析一个输入流
* @param is 文件输入流
* @param rootParserQName 解析的文件根节点
* @param rootParser 根解析器
*/
public static void start(InputStream is,
final String rootParserQName,
final SaxParser rootParser){
try {
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
parser.parse(is, new DefaultHandler(){
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if(qName == null){
return;
}
if(rootParser != null){
rootParser.startElement(uri, qName, qName, attributes);
}else if(qName.equals(rootParserQName)){
rootParser.parserStart(attributes);
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if(rootParser != null){
rootParser.characters(ch, start, length);
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if(qName == null){
return;
}
if(qName.contains(rootParserQName)){
if(rootParser != null){
rootParser.parserEnd();
}
}else if(rootParser != null){
rootParser.endElement(uri, qName, qName);
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 节点解析开始
*/
public abstract void parserStart(Attributes attributes);
/**
* 一个子节点解析结束
* @param value characters获得的值
*/
public abstract void parserElementEnd(String qName, String value);
/**
* 解析事件需要向下传递,返回需要传递的子SaxParser
*/
public abstract SaxParser dispatchTo(String qName, Attributes attributes);
/**
* 节点解析结束
*/
public abstract void parserEnd();
}
需要解析的xml文件test.xml:
<?xml version="1.0" encoding="UTF-8"?> <kml xmlns:gx="http://www.google.com/kml/ext/2.2"> <Document id="123">
<description>abc</description>
<author>csq</author>
<ExtendedData>
<Data name="TrackId">
<value>293156</value>
</Data>
<Data name="TrackTypeId">
<value>8</value>
</Data>
</ExtendedData> <Placemark>
<name>深圳湾公园</name>
<TimeStamp>
<when>2015-03-21T10:00:13Z</when>
</TimeStamp>
<Point>
<coordinates>113.93946,22.48955,9.0</coordinates>
</Point>
</Placemark> </Document> </kml>
开始解析:
根节点kml,根节点解析器KmlParser
SaxParser.start(getAssets().open("test.kml"), "kml", new Kml.KmlParser(kml));
部分节点解析实现:
public static class KmlParser extends SaxParser {
private Kml kml;
public KmlParser(Kml kml) {
super(new HashSet<String>());
this.kml = kml;
childParserQNames.add("Document");
}
@Override
public void parserStart(Attributes attributes) {
}
@Override
public void parserElementEnd(String qName, String value) {
}
@Override
public SaxParser dispatchTo(String qName, Attributes attributes) {
if(qName.equals("Document")){
return new Document.DocumentParser(kml);
}
return null;
}
@Override
public void parserEnd() {
}
}
public static class DocumentParser extends SaxParser {
private Kml kml;
private Document document;
public DocumentParser(Kml kml) {
super(new HashSet<String>());
this.kml = kml;
childParserQNames.add("ExtendedData");
childParserQNames.add("Placemark");
}
@Override
public void parserStart(Attributes attributes) {
document = new Document();
document.id = attributes.getValue("id");
}
@Override
public void parserElementEnd(String qName, String value) {
if(document == null){
return;
}
if(qName.equals("description")){
document.description = value;
}else if(qName.equals("author")){
document.author = value;
}
}
@Override
public SaxParser dispatchTo(String qName, Attributes attributes) {
if(document == null){
return null;
}
if(qName.equals("ExtendedData")){
return new ExtendedData.ExtendedDataParser(document);
}else if(qName.equals("Placemark")){
return new Placemark.PlacemarkParser(document);
}
return null;
}
@Override
public void parserEnd() {
kml.document = document;
}
}
public static class PlacemarkParser extends SaxParser {
private Document document;
private Placemark placemark;
public PlacemarkParser(Document document) {
super(new HashSet<String>(1));
childParserQNames.add("Point");
this.document = document;
}
@Override
public void parserStart(Attributes attributes) {
placemark = new Placemark();
}
@Override
public void parserElementEnd(String qName, String value) {
if(qName.equals("name")){
placemark.name = value;
}else if(qName.equals("when")){
placemark.when = value;
}
}
@Override
public SaxParser dispatchTo(String qName, Attributes attributes) {
if(qName.equals("Point")){
return new Point.PointParser(placemark);
}
return null;
}
@Override
public void parserEnd() {
document.placemark = placemark;
}
}
public static class ExtendedDataParser extends SaxParser {
private Document document;
private ExtendedData extendedData;
public ExtendedDataParser(Document document) {
super(new HashSet<String>(1));
childParserQNames.add("Data");
this.document = document;
}
@Override
public void parserStart(Attributes attributes) {
extendedData = new ExtendedData();
}
@Override
public void parserElementEnd(String qName, String value) {
}
@Override
public SaxParser dispatchTo(String qName, Attributes attributes) {
if(qName.equals("Data")){
return new Data.DataParser(extendedData);
}
return null;
}
@Override
public void parserEnd() {
document.extendedDatas = extendedData;
}
}
......
解析结果:

Android简化xml sax解析的更多相关文章
- Android 使用pull,sax解析xml
pull解析xml文件 1.获得XmlpullParser类的引用 这里有两种方法 //解析器工厂 XmlPullParserFactory factory=XmlPullParserFactory. ...
- Android:XML简介 & 解析方式对比(DOM、SAX、PULL)
目录 示意图 1. 定义 XML,即 extensible Markup Language ,是一种数据标记语言 & 传输格式 2. 作用 对数据进行标记(结构化数据).存储 & ...
- Android 之XML数据解析(2)—— SAX解析
(以下文章基本照抄郭霖大神的<第一行代码>) 在Android之 解析XML文件(1)—— Pull解析 中我们讲了Pull方式解析XML文件.今天讲另外一种方式,SAX解析XML文件. ...
- XML SAX解析
SAX是一种占用内存少且解析速度快的解析器,它采用的是事件驱动,它不需要解析完整个文档,而是按照内容顺序,看文档某个部分是否符合xml语法,如果符合就触发相应的事件.所谓的事件就是些回调方法( cal ...
- JavaEE XML SAX解析
SAX解析XML @author ixenos SAX解析工具 SAX解析工具- Sun公司提供的.内置在jdk中.org.xml.sax.* 核心的API: SAXParser类: 用于读取和解析 ...
- Java XML SAX 解析注意
版权声明: 欢迎转载,但请保留文章原始出处 作者:GavinCT 出处:http://www.cnblogs.com/ct2011/p/4002738.html 什么时候可以把解析值赋给对象 一般从网 ...
- Python—使用xml.sax解析xml文件
什么是sax? SAX是一种基于事件驱动的API. 利用SAX解析XML文档牵涉到两个部分:解析器和事件处理器. 解析器负责读取XML文档,并向事件处理器发送事件,如元素开始跟元素结束事件; 而事件处 ...
- Android网络之数据解析----SAX方式解析XML数据
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...
- 玩转iOS开发 - JSON 和 Xml 数据解析
前言 Json 和xml是网络开发中经常使用的数据格式,JSON轻量级.xml相对较复杂.所以如今用JSON的比例很大.基本上从server获取的返回数据都是JSON格式的,作为iOS开发人员,解析J ...
随机推荐
- SSH框架执行自己定义的SQL语句
直接上代码 String hsql = "delete XTable x where x.Userid= ?"; Query query = this.getSession().c ...
- IOS个人帐号推送证书创建
(IOS个人帐号推送证书制作所有步骤: 可以直接将产品推送证书和开发者推送证书一起制作到一个Identifier帐号下) 一. 首先需要创建一个id:有推送功能的(App ID Suffix)只有它才 ...
- spring3.0结合Redis在项目中的运用
推荐一个程序员的论坛网站:http://ourcoders.com/home/ 以下内容使用到的技术有:Redis缓存.SpringMVC.Maven.项目中使用了redis缓存,目的是在业务场景中, ...
- 面试问题整理笔记系列 一 Java线程类
1.sleep()和wait()区别 sleep() 方法:线程主动放弃CPU,使得线程在指定的时间内进入阻塞状态,不能得到CPU 时间,指定的时间一过,线程重新进入可执行状态.典型地,sleep() ...
- tp5页面输出时,搜索后跳转下一页的处理
tp5页面输出时,搜索功能在跳转下一页时,如果不做任何处理,会返回原有是第二页输出的数据.为了保证跳转下一页时输出的是搜索到的数据,做以下处理. (要根据自己的搜索字段进行适当修改) 页面js代码,给 ...
- PHP内核探索之变量(7)- 不平凡的字符串
切,一个字符串有什么好研究的. 别这么说,看过<平凡的世界>么,平凡的字符串也可以有不平凡的故事.试看: (1) 在C语言中,strlen计算字符串的时间复杂度是?PHP中呢? ...
- Java经典实例:使用正则表达式:测试模式
import java.util.regex.Pattern; /** * Created by Frank * 在Java中使用正则表达式:测试模式 */ public class RESimple ...
- cnodejs社区论坛4--话题列表
- 如何让C#像JavaScript一样编程
JavaScript是一门动态语言,可以动态的给对象添加属性和方法,非常方便.那么有没有一种方式可以让C#也具备动态添加属性和方法的能力,像Javascript一样进行编程? 下面就介绍一个很不错的框 ...
- 基于 jQuery 实现的精致作品集图片导航效果
今天,我们要用 jQuery 来创建一个作品集图像的导航模板.我们的想法是,以分组的方式显示一组作品集,并通过二维的方式(水平/垂直)来浏览.任一箭头或当前图像下方的小盒子可以作为导航使用. 在线演示 ...