Android簡化xml sax解析

來源:互聯網
上載者:User

標籤:

  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;        }    }

  

......

 

解析結果:

 

  

 

Android簡化xml sax解析

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.