zoukankan      html  css  js  c++  java
  • 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;
            }
        }
    

      

    ......

    解析结果:

      

  • 相关阅读:
    响应式网页设计项目#1---Tribute Page to Kobe and Gigi---致敬科比和Gigi
    Vue---第二部分
    Vue---概述 第一部分
    SaaS应用“正益工作”发布,为大中型企业轻松构建移动门户
    6.24 AppCan移动开发者大会:议程重大更新,报名即将关闭
    【6.24-AppCan移动开发大会倒计时】科大讯飞来了!
    6.24 AppCan移动开发者大会,我爱我家即将闪亮登场!
    惊曝6.24AppCan移动开发大会参展名录,现场礼品超多!
    6.24AppCan移动开发者大会价值30万的展示机会归了谁?
    6月24日AppCan移动开发者大会礼品清单遭泄露
  • 原文地址:https://www.cnblogs.com/John-Chen/p/4644103.html
Copyright © 2011-2022 走看看