Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> Android應用開發入門(十四)使用DOM解析XML

Android應用開發入門(十四)使用DOM解析XML

編輯:Android開發實例

前言

  前面已經介紹了Android平台下兩種解析XML的方法,SAX和PULL,這兩個均為事件驅動,以流的形式解析XML文檔。現在介紹一種新的方式DOM方式解析XML。

  DOM是一種用於XML文檔對象模型,可用於直接訪問XML文檔的各個部位,在DOM中文檔被模擬成樹狀,其中XML語法的每一組成部分都表示一個節點,DOM允許用戶遍歷文檔樹,從父節點移動到子節點和兄弟節點。並利用某節點類型特有的屬性(元素具有屬性,文本節點具有文本數據)。

  對於DOM而言,XML文檔中每一個成分都是一個節點。

  DOM是這樣規定的:

  1. 整個文檔是一個文檔節點。
  2. 每一個XML標簽是一個元素節點。
  3. 包含在XML元素中的文本是一個文本節點。
  4. 每一個XML屬性是一個屬性節點。

 

DOM解析XML

  DOM解析XML也是需要一個工廠類DocumentBuilderFactory,這一點和SAX、PULL類似。工廠類也是單例模式,沒有提供共有的構造函數,需要使用靜態的newInstance()方法獲得,並且需要工廠類來獲取DOM解析器實例,使用DocumentBuilderFactory.newDocumentBuilder()獲得的DocumentBuilder對象。

  當獲得Document之後,就可以使用parse()解析XML文檔,parser多個重載,可以適用於不同的輸入。

  下面介紹一下在DOM解析XML過程中,會碰上幾個對象,Element、NodeList、Node。說也不太好說清楚,畫個圖解釋一下更直觀。

  從圖上可以看出,Element為一個元素,可以通過這個元素獲取到該元素的屬性值(Attribute),以及它的子節點的集合NodeList。而NodeList作為一個裝載平級節點的集合,可以通過NodeList獲得它內裝載的所有平級節點,可以通過索引獲取。對於Node,表示最終的節點,根據圖示說的,其實Jack文本也是一個文本節點(Node),Node可以獲取其節點名稱、其值、其屬性。所以它們三個是可以相互嵌套的,也不存在說誰一定要在誰的外側或是內層。

示例程序

  既然已經說了那麼多了,現在通過一個示例程序展示一下DOM解析XML。這是一個Android應用程序,為了模擬真實的環境,通過網絡讀取IIS上的一個靜態XML文件內容。直接上代碼,注釋已經寫的很清楚了。

  IIS上的靜態XML文檔內容:

  1. <?xml version="1.0" encoding="utf-8" ?>   
  2. - <persons> 
  3. - <person id="23"> 
  4.   <name>Jack</name>   
  5.   <age>21</age>   
  6.   </person> 
  7. - <person id="20"> 
  8.   <name>Dick</name>   
  9.   <age>23</age>   
  10.   </person> 
  11.   </persons> 

 DomService,解析網絡傳輸來的XML文檔流:

  1. package cn.bgxt.service;  
  2.  
  3. import java.io.InputStream;  
  4. import java.util.ArrayList;  
  5. import java.util.List;  
  6.  
  7. import javax.xml.parsers.DocumentBuilder;  
  8. import javax.xml.parsers.DocumentBuilderFactory;  
  9. import javax.xml.parsers.ParserConfigurationException;  
  10.  
  11. import org.w3c.dom.Document;  
  12. import org.w3c.dom.Element;  
  13. import org.w3c.dom.Node;  
  14. import org.w3c.dom.NodeList;  
  15.  
  16.  
  17. import cn.bgxt.domain.Person;  
  18.  
  19. public class DomService {  
  20.  
  21.     public DomService() {  
  22.         // TODO Auto-generated constructor stub  
  23.     }  
  24.  
  25.     public static List<Person> getPersons(InputStream inputStream) throws Exception  
  26.     {  
  27.         List<Person> list=new ArrayList<Person>();  
  28.         //獲取工廠對象,以及通過DOM工廠對象獲取DOMBuilder對象  
  29.         DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();  
  30.         DocumentBuilder builder=factory.newDocumentBuilder();  
  31.         //解析XML輸入流,得到Document對象,表示一個XML文檔  
  32.         Document document=builder.parse(inputStream);  
  33.         //獲得文檔中的次以及節點,persons  
  34.         Element element=document.getDocumentElement();  
  35.         // 獲取Element下一級的person節點集合,以NodeList的形式存放。  
  36.         NodeList personNodes=element.getElementsByTagName("person");  
  37.         for(int i=0;i<personNodes.getLength();i++)  
  38.         {  
  39.             //循環獲取索引為i的person節點  
  40.             Element personElement=(Element) personNodes.item(i);  
  41.             Person person=new Person();  
  42.             //通過屬性名,獲取節點的屬性id  
  43.             person.setId(Integer.parseInt(personElement.getAttribute("id")));  
  44.             //獲取索引i的person節點下的子節點集合  
  45.             NodeList childNodes=personElement.getChildNodes();  
  46.             for(int j=0;j<childNodes.getLength();j++)  
  47.             {  
  48.                 //循環遍歷每個person下的子節點,如果判斷節點類型是ELEMENT_NODE,就可以依據節點名稱給予解析  
  49.                 if(childNodes.item(j).getNodeType()==Node.ELEMENT_NODE)  
  50.                 {  
  51.                     if("name".equals(childNodes.item(j).getNodeName()))  
  52.                     {  
  53.                         //因為文本也是一個文本節點,  
  54.                         //所以這裡讀取到name節點的時候,  
  55.                         //通過getFirstChild()可以直接獲得name節點的下的第一個節點,就是name節點後的文本節點  
  56.                         //取其value值,就是文本的內容  
  57.                         person.setName(childNodes.item(j).getFirstChild().getNodeValue());  
  58.                     }  
  59.                     else if("age".equals(childNodes.item(j).getNodeName()))  
  60.                     {  
  61.                         person.setAge(Integer.parseInt(childNodes.item(j).getFirstChild().getNodeValue()));  
  62.                     }  
  63.                 }  
  64.             }  
  65.             //把解析的person對象加入的list集合中  
  66.             list.add(person);  
  67.         }  
  68.         return list;  
  69.     }  

  從IIS服務器上獲取XML的方式,在另外一篇博客:HTTP協議。中已經介紹了,如果不明白可以去看看,這裡就不介紹了。

  Activity的布局就是一個按鈕,用於點擊出發解析事件,因為是Android4.0+的環境,需要無法在主線程中訪問網絡,需要使用到多線程的技術,並且不要網了給Android應用增加訪問網絡的權限。

  1. package cn.bgxt.xmlfordom;  
  2.  
  3. import java.io.InputStream;  
  4. import java.util.List;  
  5. import cn.bgxt.domain.Person;  
  6. import cn.bgxt.http.HttpUtils;  
  7. import cn.bgxt.service.DomService;  
  8. import android.os.Bundle;  
  9. import android.app.Activity;  
  10. import android.util.Log;  
  11. import android.view.Menu;  
  12. import android.view.View;  
  13. import android.widget.Button;  
  14.  
  15. public class MainActivity extends Activity {  
  16.  
  17.     private Button button;  
  18.       
  19.     @Override 
  20.     protected void onCreate(Bundle savedInstanceState) {  
  21.         super.onCreate(savedInstanceState);  
  22.         setContentView(R.layout.activity_main);  
  23.           
  24.         button=(Button)findViewById(R.id.btn);  
  25.         button.setOnClickListener(new View.OnClickListener() {  
  26.               
  27.             @Override 
  28.             public void onClick(View v) {  
  29.                 // Android 4.0+不能在主線程中訪問網絡  
  30.                 Thread thread=new Thread(new Runnable() {                      
  31.                     @Override 
  32.                     public void run() {  
  33.                         try {  
  34.                             String path="http://192.168.1.107:1231/persons.xml";  
  35.                             InputStream inputStream=HttpUtils.getXML(path);  
  36.                             List<Person> list=DomService.getPersons(inputStream);  
  37.                             for(Person person:list)  
  38.                             {  
  39.                                 //以日志的形式打印對象內容  
  40.                                 Log.i("DOM", person.toString());                              
  41.                             }  
  42.                         } catch (Exception e) {  
  43.                             // TODO: handle exception  
  44.                         }  
  45.                     }  
  46.                       
  47.                 });  
  48.                 thread.start();  
  49.             }  
  50.               
  51.         });  
  52.           
  53.           
  54.     }  
  55.  

  如果解析成功,可以在LogCat中查看到日志。

  示例程序源碼

總結

  現在已經講解的常用的Android應用中解析XML的方法,DOM和PULL、SAX不一樣,是文檔模型形式的,在解析的時候會把整個XML的內容都讀取到內存中,這樣對於移動設備而言,是很消耗內存的。而PULL以及SAX都是事件驅動,逐行去解析XML的內容,相對而言保證了解析速度又不會很損耗內存。所以Android應用中一般不推薦使用DOM解析XML,還是偏向於使用SAX、PULL。但是DOM也有它的優點,正因為它是把整個文檔都讀取到內存中了,可以指定需要查找的數據而無需遍歷所有的節點,對於內容比較少的XML而言,還是很方便的。所以解析XML的方法有很多,無法絕對的說明誰好誰壞,主要還是看需求設定的環境來取捨的。

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved