Android简化xml sax解析

  dom解析占用内存大(我这边需要解析各种各样的kml文件,有时4-5M的kml文件使用dom解析很多手机就内存溢出了),也需要引入第三方库,所以使用相对于节省内存很多、不需引入其他库的sax解析就是很好的选择了。因为sax解析比较复杂的xml文件特别麻烦,所以整理了一个简化android sax解析的工具。

  实现思路:和Android Touch事件传递机制一样,把需要子解析器解析的节点往下传递。

  如果有进一步简化的方法,欢迎交流!email:[email protected]。

  示例程序: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;
        }
    }

  

......

解析结果:

  

时间: 2024-10-17 02:51:43

Android简化xml sax解析的相关文章

Android中XML数据解析

转载请注明出处:http://blog.csdn.net/yegongheng/article/details/38296207 XML初步 今天我们来学习另一种非常重要的数据交换格式-XML.XML(Extensible Markup Language的缩写,意为可扩展的标记语言),它是一种元标记语言,即定义了用于定义其他特定领域有关语义的.结构化的标记语言,这些标记语言将文档分成许多部件并对这些部件加以标识.XML 文档定义方式有:文档类型定义(DTD)和XML Schema.DTD定义了文

(Android review)XML的解析与序列化

这篇博客主要用来介绍对XML文件的操作:解析与生成. Android手机内部的解析就是pull解析官网:http://xmlpull.org/所谓的解析,我们可以理解为:利用XML文件的内容来生成一个对象导出生成的xml文件后不要对其格式化,否则会出异常 1.MainActivity package com.example.xmlparsertest1; import android.os.Bundle; import android.app.Activity; import android.v

Android 使用pull,sax解析xml

pull解析xml文件 1.获得XmlpullParser类的引用 这里有两种方法 //解析器工厂 XmlPullParserFactory factory=XmlPullParserFactory.newInstance(); XmlPullParser pullParser=factory.newPullParser(); //直接获得实例XmlPullParser pullParser= Xml.newPullParser(); 2.设置解析内容 通过setInput方法设置解析内容  

Android 之XML数据解析(2)—— SAX解析

(以下文章基本照抄郭霖大神的<第一行代码>) 在Android之 解析XML文件(1)-- Pull解析 中我们讲了Pull方式解析XML文件.今天讲另外一种方式,SAX解析XML文件. 首先还是先看代码. 一. SAX解析参考代码 private void parseXMLWithSAX(String xmlData){ try{ SAXParserFactory factory = SAXParserFactory.newInstance(); XMLReader xmlReader =

Android学习笔记——SAX解析XML

XML数据源: <?xml version="1.0" encoding="utf-8"?><WeatherWindow>    <updated>2015-09-08 20:00:00</updated>    <region><![CDATA[上海]]></region>    <today>        <condition><![CDATA[晴

android之XML文件解析 -- SAX

xml文件解析之SAX 下面的实例代码主要采用的是SAX事件驱动处理机制来解析XML文件,SAX解析XML是通过逐行扫描的方式完成的,占用内存小.dom机制是将文件全部读出,然后再以树结构的形式,来完成查找.删除等操作,对内存占用较大 MyContentHandler.java     此文件是事件处理器实现 package com.example.analysisxml; import org.xml.sax.Attributes; import org.xml.sax.SAXExceptio

Android对XML文件解析

HTTP网络传输中的数据组织方式有三种方式: 1.HTML方式 2.XML方式 3.JSON方式 XML的结构解析如下: 1.节点 2.元素 3.属性和属性值 由于XML的扩展性强,致使它需要有稳定的基础规则来支持扩展,该语法规则是: 1.开始和结束标签匹配 2.嵌套标签不能互相嵌套 3.区分大小写 Android中,解析Xml数据的三种方式: 1.DOM(org.w3c.dom) "文档对象模型"方式,解析完的Xml将生成一个树状结构的对象. 2.SAX(org.xml.sax) S

Python—使用xml.sax解析xml文件

什么是sax? SAX是一种基于事件驱动的API. 利用SAX解析XML文档牵涉到两个部分:解析器和事件处理器. 解析器负责读取XML文档,并向事件处理器发送事件,如元素开始跟元素结束事件; 而事件处理器则负责对事件作出相应,对传递的XML数据进行处理. sax适于处理下面的问题: 1.对大型文件进行处理: 2.只需要文件的部分内容,或者只需从文件中得到特定信息: 3.想建立自己的对象模型的时候. 在python中使用sax方式处理xml要先引入xml.sax中的parse函数,还有xml.sa

android动画xml参数解析

本博客主要讲述的是3.0属性动画之前的动画xml参数 1 alpha 渐变透明度动画效果 <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <alpha android:duration="1000" android:fromAlpha=&