Dom parsing takes up a lot of memory (I need to parse a variety of KML files, sometimes the 4-5m KML file uses the DOM to parse a lot of phones out of memory), and we need to introduce a third-party library, so it's a good choice to use a sax parsing that saves lots of memory and does not need to introduce other libraries. Because Sax is particularly troublesome in parsing complex XML files, it organizes a tool that simplifies the parsing of Android Sax.
Implementation idea: As with the Android touch event delivery mechanism, the node that needs to parse the sub-parser is passed down.
If there is a further simplification of the method, Welcome to Exchange! Email:[email protected].
Example program: Https://github.com/John-Chen/EasySaxParser
Simplified tool SAXParser:
Public abstract class SAXParser {protected String curqname; protected StringBuilder Curvalue = new StringBuilder (); protected SAXParser SAXParser; protected String saxparserqname; /** * required to generate the node name for sub-SAXParser */protected hashset<string> childparserqnames; Public SAXParser () {} public SAXParser (hashset<string> childparserqnames) {this.childparserqnames = c Hildparserqnames; } protected void Startelement (String uri, String localname, String qName, Attributes Attributes) {if (QName = = N ull) {return; } if (SAXParser! = null) {saxparser.startelement (URI, QName, qName, attributes); }else if (childparserqnames! = null && childparserqnames.contains (qName)) {this.saxparser = Dispatchto (q Name, 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); }}}/** * begins parsing an input stream * @param is file input stream * @param rootparserqname resolved file root node * @param rootparser Root parser */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 qNa Me) 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 (); } }/** * Node parsing begins */public abstract void Parserstart (Attributes Attributes); /** * End of a child node resolution * @param value characters obtained values */public abstract void Parserelementend (String qName, String Value); /** * Parsing events need to be passed down, returning the child SAXParser */public abstract SAXParser Dispatchto (String qName, Attributes Attributes) that need to be passed ; /** * Node parsing end */public abstract void Parserend ();}
XML file Test.xml to parse:
<?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> Shenzhen Bay Park </name> <TimeStamp> <when> 2015-03-21t10:00:13z</when> </TimeStamp> <Point> <coordinates> 113.93946,22.48955,9.0</coordinates> </Point> </Placemark> </Document> </kml>
Start parsing:
Root node kml, root node resolver kmlparser
Saxparser.start (Getassets (). Open ("TEST.KML"), "KML", New Kml.kmlparser (KML));
Partial node resolution implementation:
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 (docume NT = = 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; } }
......
Parsing results:
Android simplifies XML sax parsing