Android series Network (IV)-parsing XML data using the SAX Method
I. Introduction of XML: Extensible Markup Language (XML), used to mark electronic files so that they have a structured Markup Language. It can be used to mark data and define data types, it is a source language that allows users to define their own markup language, which is explained by Baidu encyclopedia. XML is a common format for data transmission over the Internet. Like HTML, XML is SGML (Standard Generic Markup Language). Whether you need to access data over the Internet, or you may need to use XML to send data to Web Services. Android applications need to interact with the network. Otherwise, they are only stand-alone and non-interactive applications. Therefore, it is necessary to use XML during Android application development. Due to the high scalability of XML, it requires stable basic rules to support extension. Note that the syntax rules start with end tag matching. Nested labels cannot be nested with each other. Case sensitive. The XML structure is parsed as follows: the node element attributes and attribute values are in the following format: <Tag Name attribute name 1 = "attribute value 1" attribute name 1 = "attribute value 1"……> Content </Tag Name> 2. XML parsing classification in Android: The biggest advantage of the Android platform is that upper-layer applications can be developed using the Java programming language, the Java platform supports using XML in many different ways, and most XML-related APIs have been fully supported in the Android system. However, due to the limitations of the Android mobile device, there are only three methods to parse XML: DOM, Document Object Model, and Document Object Model, after the parsed XML file is parsed, an object with a tree structure is generated. SAX, simple API for Xml, notifies the program in the form of events and parses the XML. Xml pull, similar to the SAX method, parses XML in PULL mode. Iii. Introduction to SAX parsing: SAX is an xml parser with high resolution speed and low memory usage. It is very suitable for Android and other mobile devices. An event-driven file is used to parse an XML file. That is to say, it does not need to parse a complete file. In the process of parsing a document in order of content, SAX checks whether the currently read characters are valid for a part of the XML syntax. If yes, the event is triggered. The so-called events are actually some callback methods, which are defined in the ContentHandler interface. Advantages of using SAX: Because the advantage of SAX is stream processing, when a tag is encountered, it does not record the previously encountered tag. That is to say, in the startElement () method triggered by reading each node, only the name and attribute of the current signature can be known. As for the label nested structure, the upper-layer label name, it is unknown whether any child element has information related to other structures. Simple Steps to parse XML using SAX: Create a class named MyHandler, inherit from DefaultHandler, and rewrite the special method in DefaultHandler. XML parsing is completed in this class. Instantiate the factory object of a SAX Parser and get it using the SAXParserFactory. newInstance () method. Use SAXParserFactory. newSAXParser () to obtain the SAXParser object. Instantiate the MyHandler class and input the name of the node to be parsed. Use the SAXParser. parse () method to set the XML Stream and XML parsing object to be parsed. Finally, get the parsing result from the MyHandler object. The DefaultHandler class is the default base class of the SAX2 event handler. It inherits four interfaces: EntityResolver, DTDHandler, ContentHandler, and ErrorHandler. It contains all the methods of these four interfaces. Therefore, when writing an event handler, we do not need to directly implement these four interfaces, but inherit the class and then override the required methods. In the DefaultHandler inherited class, you need to override the following five methods: copy the code public void startDocument (). When the document starts, call this method, you can do some preprocessing work in it. Public void startElement (String namespaceURI, String localName, String qName, Attributes attributes) triggers this method when you read a start tag and obtains the Attributes of the element again. NamespaceURI is the namespace, localName is the tag name without the namespace prefix, and qName is the tag name with the namespace prefix. You can use attributes to obtain all attribute names and corresponding values. It should be noted that an important feature of SAX is its stream processing. When a tag is encountered, it will not record the previously encountered tag, that is, in startElement () all the information you know in the method is the name and attribute of the tag. As for the nested structure of the tag, the name of the Upper-layer tag, whether there is sub-meta, and other information related to the structure, they are all unknown, and they all need your program to complete. This makes it easier to program and process SAX than DOM. Public void characters (char [] ch, int start, int length) is used to process the content read in the XML file. The first parameter is used to store the content of the file, the following two parameters are the start position and length of the read String in this array. You can obtain the content using new String (ch, start, length. Public void endElement (String uri, String localName, String name) corresponds to the startElement () method. This method is called when an end tag is encountered. The public void endDocument () method corresponds to the startDocument () method. When the document ends, you can call this method to do some aftercare work. To copy the code, we use an XML file to explain when the preceding five methods are executed: <? Xml version = "1.0" encoding = "UTF-8"?> StartDocument <persons> startElement <person id = "01"> startElement <name nameid = "1"> startElement smyh characters </name> endElement <age> startElement 22 characters </age> endElement </person> endElement </persons> endElement SAXParserFactory class, defines a factory API so that the application can configure and obtain a SAX-based parser to parse XML documents. It has only one protected Constructor (Singleton mode), so you need to use the static newInstance () method to return to the SAXParserFactory () object. Using SAXParserFactory, you can call the. newSAXParser () method to obtain a SAXParser. Using the SAXParser object, you can execute the parser () method and set the XML Stream and parser class by passing parameters. Iv. Steps for parsing XML by using SAX: A sample program is used to explain how to parse XML files. This sample program runs on the Android platform. to simulate the actual situation, A static XML file is placed on the tomcat server, that is, a smyhvae is created in the D: \ apache-tomcat-8.0.14 \ webapps \ ROOT directory. the content of the xml file is as follows: copy the Code <? Xml version = "1.0" encoding = "UTF-8"?> <Persons> <person id = "01"> <name> smyh </name> <age> 22 </age> </person> <person id = "02"> <name> vae </name> <age> 24 </age> </person> </persons> copy the code. Note: for details about tomcat server configuration, refer to my blog: Network of Android series (3) ---- use HttpClient to send HTTP requests (send data through GET and POST methods respectively) because the IP address of my computer is 192.168.1.112. Now we enter http: // 192.168.1.112: 8080/smyhvae. xml in the browser. The result is as follows: what we need to do now is to get and parse the XML data through the Android program. In this example, read the value of the person node. Because it is an Android program, do not forget to grant it the permission to access the network. The entire Android project structure is as follows: (1) [create a tool class HttpUtils] Use URLHttpConnection to get the XML Stream on the server: we write it as a Tool class, the Code is as follows: Copy code 1 package com. example. androidsaxxml. http; 2 3 import java. io. inputStream; 4 import java.net. httpURLConnection; 5 import java.net. URL; 6 7 // tool class: Use URLHttpConnection to obtain the XML Stream 8 public class HttpUtils {9 10 public HttpUtils () {11} 12 13 // method on the server: the returned InputStream object is the XML Stream returned by the server. 14 public static InputStream getXML (String path) {// parameter path: the specific url link will be specified in MainActivity 15 try {16 URL = new url (path ); 17 if (url! = Null) 18 {19 HttpURLConnection connection = (HttpURLConnection) url. openConnection (); 20 connection. setDoInput (true); 21 connection. setConnectTimeout (3000); 22 connection. setRequestMethod ("GET"); 23 int requesetCode = connection. getResponseCode (); 24 if (requesetCode = 200) 25 {26 // if the execution is successful, return the HTTP Response stream 27 return connection. getInputStream (); 28} 29} 30} catch (Exception e) {31 // TODO: handle exception32} 33 return Null; 34} 35} copy the code (2) [Create a class MyHandler] Create a subclass MyHandler and inherit the DefaultHandler class: the most important step for parsing xml by using xml sax is to define our own Handler processing class, inherit the DefaultHandler class, and then override the callback method in it, perform xml parsing in these callback methods. The Code is as follows: Copy code 1 package com. example. androidsaxxml. handler; 2 3 import java. util. arrayList; 4 import java. util. hashMap; 5 import java. util. list; 6 7 import org. xml. sax. attributes; 8 import org. xml. sax. SAXException; 9 import org. xml. sax. helpers. defaultHandler; 10 11 12 // class: MyHandler, inherited from the DefaultHandler class, used to parse XML data. 13 // then, set the nodeName in MainActivity to instantiate MyHandler14 public class MyHandler extends DefaultHandler {15 private List <HashMap <String, String> list = null; // The parsed XML content 16 private HashMap <String, String> map = null; // The XML content 17 private String currentTag = null for the node to be recorded currently; // currently read XML node 18 private String currentValue = null; // The XML text value of the current node 19 private String nodeName = null; // name of the node to be parsed 20 21 public MyHandler (Stri Ng nodeName) {22 // set the name of the node to be parsed 23 this. nodeName = nodeName; 24} 25 26 @ Override27 public void startDocument () throws SAXException {28 // receive the notification from the beginning of the document 29 // instantiate ArrayList to store the parsed XML data 30 list = new ArrayList <HashMap <String, String> (); 31} 32 33 @ Override34 public void startElement (String uri, String localName, String qName, 35 Attributes attributes) throws SAXException {36 // notification 37 if (qName. equals (NodeName) {38 // if the name of the currently running node is the same as the name of the node to be read, HashMap39 map = new HashMap <String, String> () is instantiated (); 40} 41 // Attributes is the attribute value of the current node. If the attribute value exists, the attribute value is also read. 42 if (attributes! = Null & map! = Null) {43 for (int I = 0; I <attributes. getLength (); I ++) {44 // The read attribute value is inserted into the Map. 45 map. put (attributes. getQName (I), attributes. getValue (I); 46} 47} 48 // record the name of the current node. 49 currentTag = qName; 50} 51 52 @ Override53 public void characters (char [] ch, int start, int length) 54 throws SAXException {55 // receive notifications of character data in the element. 56 // The execution of 57 if (currentTag! = Null & map! = Null) {58 // obtain the text value of the current node. The direct array ch is the text value stored. 59 currentValue = new String (ch, start, length); 60 if (currentValue! = Null &&! CurrentValue. equals ("") 61 &&! CurrentValue. equals ("\ n") {62 // The read text must be judged not to be null, not equal to "", not equal to "\ n" 63 map. put (currentTag, currentValue); 64} 65} 66 // after reading, you need to clear the label value and the included text value of the current node. 67 currentTag = null; 68 currentValue = null; 69} 70 71 @ Override72 public void endElement (String uri, String localName, String qName) 73 throws SAXException {74 // receives the notification of element termination. 75 if (qName. equals (nodeName) {76 // If the read Union node is the node we need to pay attention to, add the map to the list to save the 77 list. add (map); 78 // clear the map and start reading the person in a new round. 79 map = null; 80} 81} 82 83 // method: Obtain the parsed data 84 public List <HashMap <String, String> getList () {85 return list; 86} 87} copy code (3) [New Class SaxService] instantiate the factory object of a SAX Parser: SAXParserFactory needs a class that calls the SAXParser object. Here we create a new SaxService class, instantiate SAXParserFactory to set the XML Stream and parser, that is, the MyHandler class in the previous step is called here. The Code is as follows: Copy code 1 package com. example. androidsaxxml. service; 2 3 import java. io. inputStream; 4 import java. util. hashMap; 5 import java. util. list; 6 7 import javax. xml. parsers. SAXParser; 8 import javax. xml. parsers. SAXParserFactory; 9 10 import com. example. androidsaxxml. handler. myHandler; 11 12 13 // class: The factory object used to instantiate a SAX Parser: SAXParserFactory14 public class SaxService {15 16 public SaxService () {17 // TODO Aut O-generated constructor stub18} 19 20 // method: parse the xml data and return it. The return value type is HashMap21 public static List <HashMap <String, String> readXML (InputStream inputStream, string nodeName) 22 {23 try {24 // instantiate the SAX factory class 25 SAXParserFactory factory = SAXParserFactory. newInstance (); 26 // instantiate the SAX Parser. 27 SAXParser sParser = factory. newSAXParser (); 28 // instantiate tool class MyHandler, set the node to be parsed 29 MyHandler myHandler = new MyHandler (nodeName); 30 // start parsing 31 sParser. parse (inputStream, myHandler); 32 // after parsing is complete, close stream 33 inputStream. close (); 34 // return the resolution result. 35 return myHandler. getList (); // return the parsed data 36} catch (Exception e) {37 // TODO: handle exception38} 39 return null; 40} 41 42} copy the core code lines 29th and 31st. (4) instantiate in MainActicity: instantiate the link path to be accessed and the node nodeName layout interface to be parsed. There is only one button control, so no layout code will be displayed here. Click the button to trigger the click event. Because it is Android4.0 +, you cannot access the network in the main Thread. You need to set up another Thread. The Thread class is used here. The Code is as follows: Copy code 1 package com. example. androidsaxxml; 2 3 import java. io. inputStream; 4 import java. util. hashMap; 5 import java. util. list; 6 7 import android. app. activity; 8 import android. OS. bundle; 9 import android. view. view; 10 import android. widget. button; 11 12 import com. example. androidsaxxml. http. httpUtils; 13 import com. example. androidsaxxml. service. saxService; 14 15 16 public class MainActivity exte Nds Activity {17 private Button button; 18 @ Override19 protected void onCreate (Bundle savedInstanceState) {20 super. onCreate (savedInstanceState); 21 setContentView (R. layout. activity_main); 22 23 button = (Button) findViewById (R. id. button1); 24 button. setOnClickListener (new View. onClickListener () {25 26 @ Override27 // click the button to enable Thread access network 28 public void onClick (View v) {29 thread Thread = new Thread (new Runnable (){ 30 31 @ Override32 public void run () {33 // set the XML document path to 34 String path = "http: // 192.168.1.112: 8080/smyhvae. xml "; 35 // call class HttpUtils: Get the XML stream from the server. 36 InputStream inputStream = HttpUtils. getXML (path); 37 try {38 // call class SaxService: parse the stream, and set the 39 List of nodes to be parsed <HashMap <String, String> list = SaxService. readXML (inputStream, "person"); 40 for (HashMap <String, String> map: list) 41 {42 // print to LogCat 43 System. out. println (map. toString (); 44} 45} catch (Exception e) {46 // TODO: handle exception47} 48} 49}); 50 thread. start (); 51} 52}); 53} 54}