Android-----解析xml文件的三種方式


SAX解析方法介紹:

  SAX(Simple API for XML)是一個解析速度快並且占用內存少的XML解析器,非常適合用於Android等移動設備。SAX解析XML文件采用的是事件驅動,也就是說,它並不需要解析完整個文檔,在按內容順序解析文檔的過程中,SAX會判斷當前讀到的字符是否合法XML語法中的某部分,如果符合就會觸發事件。所謂事件,其實就是一些回調(callback)方法,這些方法(事件)定義在ContentHandler接口。

 

Pull解析器:

  Pull解析是一個while循環,隨時可以跳出。Pull解析器的工作方式為允許你的應用程序代碼主動從解析器中獲取事件,因此可以在滿足了需要的條件后不再獲取事件,結束解析工作。

 

DOM解析:

  DOM解析XML文件時,會將XML的所有內容讀取到內存中,然后允許您使用DOM API遍歷XML樹、檢索所需的數據。因為DOM需要將所有內容讀取到內存中,所以內存的消耗比較大,不建議使用DOM解析XML文件,若文件較小可行。

 

首先新建一個xml文件,放在res/raw目錄下,沒有raw目錄則新建一個。

要解析的itcase.xml內容如下:

<?xml version="1.0" encoding="UTF-8"?>
<persons>
    <person id="23">
        <name>liming</name>
        <age>30</age>
    </person>
    <person id="20">
        <name>lixiang</name>
        <age>25</age>
    </person>
</persons>

新建一個類存放解析的內容

Person.java如下:

 1 public class Person {
 2     private int id;
 3     private String name;
 4     private int age;
 5 
 6     public int getId() {
 7         return id;
 8     }
 9 
10     public void setId(int id) {
11         this.id = id;
12     }
13 
14     public String getName() {
15         return name;
16     }
17 
18     public void setName(String name) {
19         this.name = name;
20     }
21 
22     public int getAge() {
23         return age;
24     }
25 
26     public void setAge(int age) {
27         this.age = age;
28     }
29 }

以上所需要的准備好了,就開始解析xml工作:

首先是SAX解析

新建一個 XMLContentHandler.java文件內容如下:

 1 public class XMLContentHandler extends DefaultHandler{
 2 
 3     private List<Person> persons = null;
 4     private Person currentPerson;
 5     private String tagName = null;//當前解析的元素標簽
 6 
 7     public List<Person> getPersons() {
 8         return persons;
 9     }
10 
11     @Override/**【文檔開始時,調用此方法】**/
12     public void startDocument() throws SAXException {
13         persons = new ArrayList<>();
14     }
15 
16     @Override/**【標簽開始時,調用此方法】**/
17     /**【uri是命名空間|localName是不帶命名空間前綴的標簽名|qName是帶命名空間前綴的標簽名|attributes可以得到所有的屬性名和對應的值】**/
18     public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
19         if (localName.equals("person")) {
20             currentPerson = new Person();
21             currentPerson.setId(Integer.parseInt(attributes.getValue("id")));
22         }
23         this.tagName = localName;
24     }
25 
26     @Override/**【接收標簽中字符數據時,調用此方法】**/
27     /**【ch存放標簽中的內容,start是起始位置,length是內容長度】**/
28     public void characters(char[] ch, int start, int length) throws SAXException {
29         if (tagName != null) {
30             String data = new String(ch, start, length);
31             if (tagName.equals("name")) {
32                 this.currentPerson.setName(data);
33             } else if (tagName.equals("age")) {
34                 this.currentPerson.setAge(Short.parseShort(data));
35             }
36         }
37     }
38 
39     @Override/**【標簽結束時,調用此方法】**/
40     /**【localName表示元素本地名稱(不帶前綴),qName表示元素的限定名(帶前綴)】**/
41     public void endElement(String uri, String localName, String qName) throws SAXException {
42         if (localName.equals("person")) {
43             persons.add(currentPerson);
44             currentPerson = null;
45         }
46         this.tagName = null;
47     }
48 
49 
50 }

 

新建一個調用XMLContentHandler中方法的XMLParsingMethods.java類,內容如下:

 

 1 public class XMLParsingMethods {
 2 
 3     /**【SAX解析XML文件】**/
 4     public static List<Person> readXmlBySAX(InputStream inputStream) {
 5         try {
 6             /**【創建解析器】**/
 7             SAXParserFactory spf = SAXParserFactory.newInstance();
 8             SAXParser saxParser = spf.newSAXParser();
 9             XMLContentHandler handler = new XMLContentHandler();
10             saxParser.parse(inputStream, handler);
11             inputStream.close();
12             return handler.getPersons();
13         } catch (Exception e) {
14             e.printStackTrace();
15         }
16         return null;
17     }
18 }

 

到這里,SAX解析XML文件工作已經完成了,調用XMLPersingMethods中的readXmlBySAX就可以解析itcase.xml文件。在這里就先不調用,把三種的解析方法講完再一並調用。

 

DOM解析XML文件:直接在XMLPersingMethods中添加解析方法

 

 1 public class XMLParsingMethods {
 2 
 3     /**【SAX解析XML文件】**/
 4     public static List<Person> readXmlBySAX(InputStream inputStream) {
 5         ......
 6     }
 7 
 8     /**【DOM解析XML文件】**/
 9     public static List<Person> readXmlByDOM(InputStream inputStream){
10         List<Person> persons = new ArrayList<>();
11         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
12         try {
13             DocumentBuilder builder = factory.newDocumentBuilder();
14             Document dom = builder.parse(inputStream);
15 
16             Element root = dom.getDocumentElement();
17             /**【查找所有person節點】**/
18             NodeList items = root.getElementsByTagName("person");
19             for (int i = 0; i < items.getLength(); i++) {
20                 Person person = new Person();
21 
22                 /**【得到第一個person的節點】**/
23                 Element personNode = (Element) items.item(i);
24 
25                 /**【獲取person節點的id屬性】**/
26                 person.setId(new Integer(personNode.getAttribute("id")));
27 
28                 /**【獲取person節點下的所有子節點(標簽之間的空白節點和name/age節點)】**/
29                 NodeList childsNodes = personNode.getChildNodes();
30 
31                 /**【遍歷所有子節點】**/
32                 for (int j = 0; j < childsNodes.getLength(); j++) {
33                     Node node = (Node) childsNodes.item(j);
34 
35                     /**【判斷是否為元素類型】**/
36                     if(node.getNodeType() == Node.ELEMENT_NODE){
37                         Element childNode = (Element) node;
38                         /**【判斷是否是name元素】**/
39                         if ("name".equals(childNode.getNodeName())) {
40                             /**【獲取name元素下的text節點,然后從text節點獲取數據】**/
41                             person.setName(childNode.getFirstChild().getNodeValue());
42                             /**【判斷是否是age元素】**/
43                         }else if("age".equals(childNode.getNodeName())){
44                             /**【獲取age元素下的text節點,然后從text節點獲取數據】**/
45                             person.setAge(new Short(childNode.getFirstChild().getNodeValue()));
46                         }
47                     }
48                 }
49                 persons.add(person);
50             }
51             inputStream.close();
52         } catch (Exception e) {
53             e.printStackTrace();
54         }
55         return persons;
56     }
57 }

 

至此,DOM解析XML文件工作也已經完成了。

 

Pull解析器解析XML文件:

 

 1 public class XMLParsingMethods {
 2 
 3     /**【SAX解析XML文件】**/
 4     public static List<Person> readXmlBySAX(InputStream inputStream) {
 5         ......
 6     }
 7 
 8     /**【DOM解析XML文件】**/
 9     public static List<Person> readXmlByDOM(InputStream inputStream){
10        ......
11     }
12 
13     /**【Pull解析器解析XML文件】**/
14     public static List<Person> readXmlByPull(InputStream inputStream){
15         XmlPullParser parser = Xml.newPullParser();
16         try {
17             parser.setInput(inputStream,"UTF-8");
18             int eventType = parser.getEventType();
19 
20             Person currenPerson = null;
21             List<Person> persons = null;
22 
23             while(eventType != XmlPullParser.END_DOCUMENT){
24                 switch (eventType){
25                     case XmlPullParser.START_DOCUMENT:/**【文檔開始事件】**/
26                         persons = new ArrayList<>();
27                         break;
28                     case XmlPullParser.START_TAG:/**【元素(即標簽)開始事件】**/
29                         String name = parser.getName();
30                         if(name.equals("person")){
31                             currenPerson = new Person();
32                             currenPerson.setId(new Integer(parser.getAttributeValue(null,"id")));
33                         }else if(currenPerson !=null){
34                             if(name.equals("name")){/**【判斷標簽名(元素名)是否為name】**/
35                                 currenPerson.setName(parser.nextText());/**【如果后面是text元素,即返回它的值】**/
36                             }else if(name.equals("age")){
37                                 currenPerson.setAge(new Integer(parser.nextText()));
38                             }
39                         }
40                         break;
41                     case XmlPullParser.END_TAG:/**【元素結束事件】**/
42                         if(parser.getName().equalsIgnoreCase("person") && currenPerson != null){
43                             persons.add(currenPerson);
44                             currenPerson = null;
45                         }
46                         break;
47                 }
48                 eventType = parser.next();
49             }
50             inputStream.close();
51             return persons;
52         } catch (Exception e) {
53             e.printStackTrace();
54         }
55         return null;
56     }
57 }

 

至此,SAX、DOM、Pull三種解析XML文件准備好了,接下來分別調用方法:

 

布局文件:

 

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout
 3     xmlns:android="http://schemas.android.com/apk/res/android"
 4     xmlns:tools="http://schemas.android.com/tools"
 5     android:layout_width="match_parent"
 6     android:layout_height="match_parent"
 7     android:orientation="vertical"
 8     tools:context="com.hs.example.exampleapplication.PersonXML">
 9 
10         <TextView
11             android:id="@+id/data"
12             android:layout_width="match_parent"
13             android:layout_height="wrap_content"
14             android:textSize="20sp"
15             android:text="Xml數據:"/>
16 
17     <Button
18         android:id="@+id/btn_read"
19         android:layout_width="match_parent"
20         android:layout_height="wrap_content"
21         android:textSize="25sp"
22         android:text="解析XML文件"/>
23 
24 </LinearLayout>

 

方法調用:

 

 1 public class PersonXML extends AppCompatActivity implements View.OnClickListener{
 2 
 3     Button btn_read;
 4     TextView data ;
 5     List<Person> personList = null;
 6     InputStream inputStream;
 7 
 8     @Override
 9     protected void onCreate(Bundle savedInstanceState) {
10         super.onCreate(savedInstanceState);
11         setContentView(R.layout.activity_personxml);
12 
13         btn_read = this.findViewById(R.id.btn_read);
14         btn_read.setOnClickListener(this);
15 
16         data = this.findViewById(R.id.data);
17 
18         personList = new ArrayList<>();
19     }
20 
21     @Override
22     public void onClick(View view) {
23         switch (view.getId()){
24             case R.id.btn_read:
25                 String result = "";
26                 inputStream = getResources().openRawResource(R.raw.itcase);
27                 if(inputStream == null){
28                     Toast.makeText(this,"InputStream is null",Toast.LENGTH_SHORT).show();
29                 }else{
30                     personList = XMLParsingMethods.readXmlByPull(inputStream); //調用Pull
31                     //personList = XMLParsingMethods.readXmlBySAX(inputStream);//調用SAX
32                     //personList = XMLParsingMethods.readXmlByDOM(inputStream);//調用DOM
33                     if(personList!=null){
34                         for(int i = 0 ;i <personList.size();i++){
35                             String message = "id = " + personList.get(i).getId() + " , name = " + personList.get(i).getName()
36                                     + " , age = " + personList.get(i).getAge() + ".\n";
37                             result += message;
38                         }
39                     }else{
40                         Toast.makeText(this,"persons is null",Toast.LENGTH_SHORT).show();
41                     }
42                     data.setText(result);
43                     XMLParsingMethods.createXmlFile(personList);//這里是接下來使用Pull解析器生成XML文件的方法調用
44                 }
45                 break;
46         }
47 
48     }
49 }

 

運行效果:

 

 

順道講下使用Pull解析器生成XML文件:

 

 1 public class XMLParsingMethods {
 2 
 3     /**【SAX解析XML文件】**/
 4     public static List<Person> readXmlBySAX(InputStream inputStream) {
 5         ......
 6     }
 7 
 8     /**【DOM解析XML文件】**/
 9     public static List<Person> readXmlByDOM(InputStream inputStream){
10         ......
11     }
12 
13     /**【Pull解析器解析XML文件】**/
14     public static List<Person> readXmlByPull(InputStream inputStream){
15         ......
16     }
17 
18     /**【使用Pull解析器生成XML文件內容】**/
19     public static String WriteXML(List<Person> persons,Writer writer ){
20         XmlSerializer serializer = Xml.newSerializer();
21         try {
22             serializer.setOutput(writer);
23             serializer.startDocument("UTF-8",true);
24 
25             /**【第一個參數為命名空間,不使用命名空間可以設置為null】**/
26             serializer.startTag("","persons");
27             /**【XML文件中要生成的內容】**/
28             for(Person person : persons){
29                 serializer.startTag("","person");
30                 serializer.attribute("", "id", String.valueOf(person.getId()) );
31 
32                 serializer.startTag("","name");
33                 serializer.text(person.getName());
34                 serializer.endTag("","name");
35 
36                 serializer.startTag("","age");
37                 serializer.text(String.valueOf(person.getAge()));
38                 serializer.endTag("","age");
39 
40                 serializer.endTag("","person");
41             }
42             serializer.endTag("","persons");
43             serializer.endDocument();
44             return writer.toString();
45         } catch (Exception e) {
46             e.printStackTrace();
47         }
48         return null;
49     }
50 
51     /**【生成XML文件代碼】**/
52     public static void createXmlFile(List<Person> persons){
53         if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
54             try {
55                 File sdCard = Environment.getExternalStorageDirectory();
56                 File xmlFile = new File(sdCard + File.separator + "testFolder/" + "myitcast.xml");
57                 FileOutputStream outStream =  new FileOutputStream(xmlFile);
58                 OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outStream , "UTF-8");
59                 BufferedWriter writerFile = new BufferedWriter(outputStreamWriter);
60 
61                 WriteXML(persons,writerFile);
62                 writerFile.flush();
63                 writerFile.close();
64             } catch (Exception e) {
65                 e.printStackTrace();
66             }
67         }
68     }
69 }

 

運行后:

 

 

 

新建文件要先獲得文件操作系統權限,推薦文章:https://blog.csdn.net/weixin_44001878/article/details/89520246

 

以上內容參考於:https://www.open-open.com/lib/view/open1392780226397.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM