你的位置:首页 > 操作系统

[操作系统]Android简化xml sax解析


  dom解析占用内存大(我这边需要解析各种各样的kml文件,有时4-5M的kml文件使用dom解析很多手机就内存溢出了),也需要引入第三方库,所以使用相对于节省内存很多、不需引入其他库的sax解析就是很好的选择了。因为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();}

 

需要解析的

<?

   

开始解析:

根节点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;    }  }

  

......

 

解析结果: