天天看點

Android XML解析學習——建立XML .

一.基礎知識

在前面的學習過程中,我們基本上比較全面的學習了Android平台上讀取XML文檔的方法,介紹了使用Java SAX、Android SAX、DOM和Pull等各種方式來讀取XML文檔内容。

目前為止,我們一直專注于解析已有的XML文檔,實際上我們也是需要讀XML的情形比較多。但是我們可能也有寫XML的需要,應用程式可能需要将 XML 發送到遠端伺服器,或者需要以XML的形式儲存資料等。是以在這部分内容中我們就來學習下Android平台上建立XML的方法。

Android系統中和建立XML相關的包為org.xmlpull.v1,在這個包中不僅提供了用來解析XML的Pull方式解析器XmlPullParser,還提供了一個用于建立XML的XmlSerializer。XmlSerializer沒有像XmlPullParser那樣提取XML事件,而是把它們推出到資料流OutputStream或Writer中。XmlSerializer提供了很直覺的API,即使用startDocument開始文檔,endDocument結束文檔,startTag開始元素,endTag結束元素,text添加文本等。

下面我們就用上面介紹的建立XML方式來實作把解析出來的USGS地震資料重新儲存為一個更簡單的XML檔案的Demo例子。

二.執行個體開發

我們要完成的效果圖如下圖1所示:

Android XML解析學習——建立XML .

 圖1 建立XML

首先解析USGS的地震資料并以ListView的方式顯示,然後點選最上方的“Create XML”按鈕就會重新把解析獲得的地震資料重新建立為一個XML檔案。

建立一個Android工程AndroidXMLDemoSerialize。

添加進之前Demo工程AndroidXMLDemoSaxII中的EarthquakeEntry.java和AndroidSaxEarthquakeHandler.java檔案。如果需要從本地讀取xml資料的話,同時在assets檔案夾下添加儲存為xml格式了的USGS地震資料USGS_Earthquake_1M2_5.xml,如果需要聯網讀取的話,在manifest.xml檔案中添權重限:

[xhtml] view plain copy print ?

  1. <uses-permission android:name="android.permission.INTERNET" />  

<uses-permission android:name="android.permission.INTERNET" />

并修改res/layout下的main.xml為:

[xhtml] view plain copy print ?

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     >  
  7.   <Button  
  8.     android:id="@+id/serializeBtn"  
  9.     android:layout_width="fill_parent"   
  10.     android:layout_height="wrap_content"  
  11.     >  
  12.   </Button>  
  13.   <ListView  
  14.     android:id="@+id/list"  
  15.     android:layout_width="fill_parent"   
  16.     android:layout_height="fill_parent"  
  17.   />  
  18. </LinearLayout>  

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <Button android:id="@+id/serializeBtn" android:layout_width="fill_parent" android:layout_height="wrap_content" > </Button> <ListView android:id="@+id/list" android:layout_width="fill_parent" android:layout_height="fill_parent" /></LinearLayout>

接下來就來建立添加一個類SerializeEarthquakeHandler,用來建立XML,内容如下: 

[java] view plain copy print ?

  1. public class SerializeEarthquakeHandler {  
  2.     //寫Xml資料   
  3.     public String writeXml(ArrayList<EarthquakeEntry> earthquakeEntryList)  
  4.     {  
  5.         StringWriter xmlWriter = new StringWriter();  
  6.         try {  
  7.             //建立XmlSerializer,有兩種方式   
  8.             XmlPullParserFactory pullFactory;  
  9.             //方式一:使用工廠類XmlPullParserFactory的方式   
  10.             pullFactory = XmlPullParserFactory.newInstance();  
  11.             XmlSerializer xmlSerializer = pullFactory.newSerializer();  
  12.             //方式二:使用Android提供的實用工具類android.util.Xml   
  13. //          XmlSerializer xmlSerializer = Xml.newSerializer();     
  14.         xmlSerializer.setOutput(xmlWriter);  
  15.             //開始具體的寫xml   
  16.             //<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>   
  17.             xmlSerializer.startDocument("UTF-8", true);  
  18.             //<feed number="25">   
  19.             xmlSerializer.startTag("", "feed");  
  20.             xmlSerializer.attribute("", "number", String.valueOf(earthquakeEntryList.size()));  
  21.             for(EarthquakeEntry earthquakeEntry : earthquakeEntryList)  
  22.             {  
  23.                 //<entry>   
  24.                 xmlSerializer.startTag("", "entry");  
  25.                 //<title>Vanuatu</title>   
  26.                 xmlSerializer.startTag("", "title");  
  27.                 xmlSerializer.text(earthquakeEntry.getPlace());  
  28.                 xmlSerializer.endTag("", "title");  
  29.                 //<magnitude>5.3</magnitude>   
  30.                 xmlSerializer.startTag("", "magnitude");  
  31.                 xmlSerializer.text(String.valueOf(earthquakeEntry.getMagnitude()));  
  32.                 xmlSerializer.endTag("", "magnitude");  
  33.                 //<updated>2010-09-26 06:44:37</updated>   
  34.                 xmlSerializer.startTag("", "updated");  
  35.                 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  36.                 String dateString = sdf.format(earthquakeEntry.getDate());  
  37.                 xmlSerializer.text(dateString);  
  38.                 xmlSerializer.endTag("", "updated");  
  39.                 //<link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/us2010brar.php</link>   
  40.                 xmlSerializer.startTag("", "link");  
  41.                 xmlSerializer.text(earthquakeEntry.getLink());  
  42.                 xmlSerializer.endTag("", "link");  
  43.                 //<latitude>-14.3009</latitude>   
  44.                 xmlSerializer.startTag("", "latitude");  
  45.                 xmlSerializer.text(String.valueOf(earthquakeEntry.getLocation().getLatitude()));  
  46.                 xmlSerializer.endTag("", "latitude");  
  47.                 //<longitude>167.9491</longitude>   
  48.                 xmlSerializer.startTag("", "longitude");  
  49.                 xmlSerializer.text(String.valueOf(earthquakeEntry.getLocation().getLongitude()));  
  50.                 xmlSerializer.endTag("", "longitude");  
  51.                 //<elev>-80100.0</elev>   
  52.                 xmlSerializer.startTag("", "elev");  
  53.                 xmlSerializer.text(String.valueOf(earthquakeEntry.getElev()));  
  54.                 xmlSerializer.endTag("", "elev");  
  55.                 //</entry>   
  56.                 xmlSerializer.endTag("", "entry");  
  57.             }  
  58.             //</feed>   
  59.             xmlSerializer.endTag("", "feed");  
  60.             xmlSerializer.endDocument();  
  61.         } catch (Exception e) {  
  62.             // TODO Auto-generated catch block   
  63.             e.printStackTrace();  
  64.         }  
  65.         return xmlWriter.toString();          
  66.     }  
  67. }  

public class SerializeEarthquakeHandler { //寫Xml資料 public String writeXml(ArrayList<EarthquakeEntry> earthquakeEntryList) { StringWriter xmlWriter = new StringWriter(); try { //建立XmlSerializer,有兩種方式 XmlPullParserFactory pullFactory; //方式一:使用工廠類XmlPullParserFactory的方式 pullFactory = XmlPullParserFactory.newInstance(); XmlSerializer xmlSerializer = pullFactory.newSerializer(); //方式二:使用Android提供的實用工具類android.util.Xml// XmlSerializer xmlSerializer = Xml.newSerializer(); xmlSerializer.setOutput(xmlWriter); //開始具體的寫xml //<?xml version='1.0' encoding='UTF-8' standalone='yes' ?> xmlSerializer.startDocument("UTF-8", true); //<feed number="25"> xmlSerializer.startTag("", "feed"); xmlSerializer.attribute("", "number", String.valueOf(earthquakeEntryList.size())); for(EarthquakeEntry earthquakeEntry : earthquakeEntryList) { //<entry> xmlSerializer.startTag("", "entry"); //<title>Vanuatu</title> xmlSerializer.startTag("", "title"); xmlSerializer.text(earthquakeEntry.getPlace()); xmlSerializer.endTag("", "title"); //<magnitude>5.3</magnitude> xmlSerializer.startTag("", "magnitude"); xmlSerializer.text(String.valueOf(earthquakeEntry.getMagnitude())); xmlSerializer.endTag("", "magnitude"); //<updated>2010-09-26 06:44:37</updated> xmlSerializer.startTag("", "updated"); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String dateString = sdf.format(earthquakeEntry.getDate()); xmlSerializer.text(dateString); xmlSerializer.endTag("", "updated"); //<link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/us2010brar.php</link> xmlSerializer.startTag("", "link"); xmlSerializer.text(earthquakeEntry.getLink()); xmlSerializer.endTag("", "link"); //<latitude>-14.3009</latitude> xmlSerializer.startTag("", "latitude"); xmlSerializer.text(String.valueOf(earthquakeEntry.getLocation().getLatitude())); xmlSerializer.endTag("", "latitude"); //<longitude>167.9491</longitude> xmlSerializer.startTag("", "longitude"); xmlSerializer.text(String.valueOf(earthquakeEntry.getLocation().getLongitude())); xmlSerializer.endTag("", "longitude"); //<elev>-80100.0</elev> xmlSerializer.startTag("", "elev"); xmlSerializer.text(String.valueOf(earthquakeEntry.getElev())); xmlSerializer.endTag("", "elev"); //</entry> xmlSerializer.endTag("", "entry"); } //</feed> xmlSerializer.endTag("", "feed"); xmlSerializer.endDocument(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return xmlWriter.toString(); }}

在建立XML的方法中

    //寫Xml資料

    public String writeXml(ArrayList<EarthquakeEntry> earthquakeEntryList)

首先建立XmlSerializer,

[java] view plain copy print ?

  1.             //建立XmlSerializer,有兩種方式   
  2.             XmlPullParserFactory pullFactory;  
  3.             //方式一:使用工廠類XmlPullParserFactory的方式   
  4.             pullFactory = XmlPullParserFactory.newInstance();  
  5.             XmlSerializer xmlSerializer = pullFactory.newSerializer();  
  6.             //方式二:使用Android提供的實用工具類android.util.Xml   
  7. //          XmlSerializer xmlSerializer = Xml.newSerializer();  

//建立XmlSerializer,有兩種方式 XmlPullParserFactory pullFactory; //方式一:使用工廠類XmlPullParserFactory的方式 pullFactory = XmlPullParserFactory.newInstance(); XmlSerializer xmlSerializer = pullFactory.newSerializer(); //方式二:使用Android提供的實用工具類android.util.Xml// XmlSerializer xmlSerializer = Xml.newSerializer();

建立XmlSerializer有兩種方式,一種是使用我們介紹的org.xmlpull.v1包中的工廠類XmlPullParserFactory。除了這種方式外,還可以使用Android SDK提供的實用工具包android.util中的類Xml的newSerializer()方法直接建立。

接着為XmlSerializer設定一個輸出的Writer,

xmlSerializer.setOutput(xmlWriter);

這裡将事件推送到了一個 java.io.StringWriter 執行個體中。

然後就可以使用具體的startDocument開始文檔,endDocument結束文檔,startTag開始元素,endTag結束元素,text添加文本等方法來建立具體的XML文檔内容,具體方法參考上面的代碼部分。從代碼中我們可以看到,使用XmlSerializer建立XML還是相當直覺和友善的。

最後添加AndroidXMLDemoSerialize.java檔案中的内容為:

[java] view plain copy print ?

  1. public class AndroidXMLDemoSerialize extends Activity {  
  2.     //定義顯示的List相關變量   
  3.     ListView list;  
  4.     Button serializeBtn;  
  5.     ArrayAdapter<EarthquakeEntry> adapter;  
  6.     ArrayList<EarthquakeEntry> earthquakeEntryList;  
  7.     @Override  
  8.     public void onCreate(Bundle savedInstanceState) {  
  9.         super.onCreate(savedInstanceState);  
  10.         setContentView(R.layout.main);  
  11.         //用于建立XML的按鈕   
  12.         serializeBtn = (Button)findViewById(R.id.serializeBtn);  
  13.         serializeBtn.setEnabled(false);  
  14.         //擷取地震資料流   
  15.         InputStream earthquakeStream = readEarthquakeDataFromFile();  
  16.         //Android Sax方式進行解析   
  17.         AndroidSaxEarthquakeHandler androidSaxHandler = new AndroidSaxEarthquakeHandler();  
  18.         earthquakeEntryList = androidSaxHandler.parse(earthquakeStream);  
  19.         //用ListView進行顯示   
  20.         list = (ListView)this.findViewById(R.id.list);  
  21.         adapter = new ArrayAdapter<EarthquakeEntry>(this, android.R.layout.simple_list_item_1, earthquakeEntryList);  
  22.         list.setAdapter(adapter);  
  23.         serializeBtn.setEnabled(true);  
  24.         //點選按鈕開始建立XML   
  25.         serializeBtn.setOnClickListener(new OnClickListener() {   
  26.             @Override  
  27.             public void onClick(View v) {  
  28.                 // TODO Auto-generated method stub   
  29.                 //構造xml   
  30.                 SerializeEarthquakeHandler serializeHandler = new SerializeEarthquakeHandler();  
  31.                 String earthquakeXml = serializeHandler.writeXml(earthquakeEntryList);  
  32.                 //Log列印寫成的xml資料   
  33.                 Log.v("XmlSerialize", earthquakeXml);          
  34.                 //把寫成的xml資料輸出到檔案   
  35.                 OutputStream outStream;  
  36.                 try {  
  37.                     outStream = openFileOutput("earthquake.xml", MODE_PRIVATE);  
  38.                     OutputStreamWriter outStreamWriter = new OutputStreamWriter(outStream);  
  39.                     outStreamWriter.write(earthquakeXml);  
  40.                     outStreamWriter.close();  
  41.                     outStream.close();  
  42.                 } catch (Exception e) {  
  43.                     // TODO Auto-generated catch block   
  44.                     e.printStackTrace();  
  45.                 }  
  46.             }  
  47.         });  
  48.     }  
  49.     private InputStream readEarthquakeDataFromFile()  
  50.     {  
  51.         //從本地擷取地震資料   
  52.         InputStream inStream = null;  
  53.         try {  
  54.             inStream = this.getAssets().open("USGS_Earthquake_1M2_5.xml");  
  55.         } catch (IOException e) {  
  56.             // TODO Auto-generated catch block   
  57.             e.printStackTrace();  
  58.         }  
  59.         return inStream;  
  60.     }  
  61.     private InputStream readEarthquakeDataFromInternet()  
  62.     {  
  63.         //從網絡上擷取實時地震資料   
  64.         URL infoUrl = null;  
  65.         InputStream inStream = null;  
  66.         try {  
  67.             infoUrl = new URL("http://earthquake.usgs.gov/earthquakes/catalogs/1day-M2.5.xml");  
  68.             URLConnection connection = infoUrl.openConnection();  
  69.             HttpURLConnection httpConnection = (HttpURLConnection)connection;  
  70.             int responseCode = httpConnection.getResponseCode();  
  71.             if(responseCode == HttpURLConnection.HTTP_OK)  
  72.             {  
  73.                 inStream = httpConnection.getInputStream();  
  74.             }  
  75.         } catch (MalformedURLException e) {  
  76.             // TODO Auto-generated catch block   
  77.             e.printStackTrace();  
  78.         } catch (IOException e) {  
  79.             // TODO Auto-generated catch block   
  80.             e.printStackTrace();  
  81.         }  
  82.         return inStream;  
  83.     }  
  84. }  

public class AndroidXMLDemoSerialize extends Activity { /** Called when the activity is first created. */ //定義顯示的List相關變量 ListView list; Button serializeBtn; ArrayAdapter<EarthquakeEntry> adapter; ArrayList<EarthquakeEntry> earthquakeEntryList; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //用于建立XML的按鈕 serializeBtn = (Button)findViewById(R.id.serializeBtn); serializeBtn.setEnabled(false); //擷取地震資料流 InputStream earthquakeStream = readEarthquakeDataFromFile(); //Android Sax方式進行解析 AndroidSaxEarthquakeHandler androidSaxHandler = new AndroidSaxEarthquakeHandler(); earthquakeEntryList = androidSaxHandler.parse(earthquakeStream); //用ListView進行顯示 list = (ListView)this.findViewById(R.id.list); adapter = new ArrayAdapter<EarthquakeEntry>(this, android.R.layout.simple_list_item_1, earthquakeEntryList); list.setAdapter(adapter); serializeBtn.setEnabled(true); //點選按鈕開始建立XML serializeBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub //構造xml SerializeEarthquakeHandler serializeHandler = new SerializeEarthquakeHandler(); String earthquakeXml = serializeHandler.writeXml(earthquakeEntryList); //Log列印寫成的xml資料 Log.v("XmlSerialize", earthquakeXml); //把寫成的xml資料輸出到檔案 OutputStream outStream; try { outStream = openFileOutput("earthquake.xml", MODE_PRIVATE); OutputStreamWriter outStreamWriter = new OutputStreamWriter(outStream); outStreamWriter.write(earthquakeXml); outStreamWriter.close(); outStream.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); } private InputStream readEarthquakeDataFromFile() { //從本地擷取地震資料 InputStream inStream = null; try { inStream = this.getAssets().open("USGS_Earthquake_1M2_5.xml"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return inStream; } private InputStream readEarthquakeDataFromInternet() { //從網絡上擷取實時地震資料 URL infoUrl = null; InputStream inStream = null; try { infoUrl = new URL("http://earthquake.usgs.gov/earthquakes/catalogs/1day-M2.5.xml"); URLConnection connection = infoUrl.openConnection(); HttpURLConnection httpConnection = (HttpURLConnection)connection; int responseCode = httpConnection.getResponseCode(); if(responseCode == HttpURLConnection.HTTP_OK) { inStream = httpConnection.getInputStream(); } } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return inStream; }}

程式前部分是使用Android SAX的方式解析XML文檔,然後在按鈕的點選回調函數中把解析獲得的地震資料重新建立為XML文檔的形式,并分别用Log列印和儲存為檔案。

[java] view plain copy print ?

  1. //點選按鈕開始建立XML   
  2. serializeBtn.setOnClickListener(new OnClickListener() {   
  3.     @Override  
  4.     public void onClick(View v) {  
  5.         // TODO Auto-generated method stub   
  6.         //構造xml   
  7.         SerializeEarthquakeHandler serializeHandler = new SerializeEarthquakeHandler();  
  8.         String earthquakeXml = serializeHandler.writeXml(earthquakeEntryList);  
  9.         //Log列印寫成的xml資料   
  10.         Log.v("XmlSerialize", earthquakeXml);          
  11.         //把寫成的xml資料輸出到檔案   
  12.         OutputStream outStream;  
  13.         try {  
  14.             outStream = openFileOutput("earthquake.xml", MODE_PRIVATE);  
  15.             OutputStreamWriter outStreamWriter = new OutputStreamWriter(outStream);  
  16.             outStreamWriter.write(earthquakeXml);  
  17.             outStreamWriter.close();  
  18.             outStream.close();  
  19.         } catch (Exception e) {  
  20.             // TODO Auto-generated catch block   
  21.             e.printStackTrace();  
  22.         }  
  23.     }  
  24. });  

//點選按鈕開始建立XML serializeBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub //構造xml SerializeEarthquakeHandler serializeHandler = new SerializeEarthquakeHandler(); String earthquakeXml = serializeHandler.writeXml(earthquakeEntryList); //Log列印寫成的xml資料 Log.v("XmlSerialize", earthquakeXml); //把寫成的xml資料輸出到檔案 OutputStream outStream; try { outStream = openFileOutput("earthquake.xml", MODE_PRIVATE); OutputStreamWriter outStreamWriter = new OutputStreamWriter(outStream); outStreamWriter.write(earthquakeXml); outStreamWriter.close(); outStream.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } });

完成了,可以儲存運作看下效果。

當點選螢幕上方的“Create XML”按鈕時,程式就會建立一個形式更加簡單的XML文檔,同時在DDMS的LogCat裡列印出建立的XML文檔内容,如下圖2所示:

Android XML解析學習——建立XML .

圖2 Log列印出的建立的XML文檔内容

同時還會把建立的XML以檔案的形式儲存在系統中,我們可以在DDMS的File Explorer的data/data/com.ichliebephone.xml.serialize/files檔案夾下看到,如下圖3所示:

Android XML解析學習——建立XML .

圖3 儲存着的建立出來的XML檔案

并且我們可以把這個檔案導出到電腦上,可以看到裡面的内容為:

[xhtml] view plain copy print ?

  1. <?xml version='1.0' encoding='UTF-8' standalone='yes' ?>  
  2. <feed number="25">  
  3.     <entry>  
  4.         <title>Vanuatu</title>  
  5.         <magnitude>5.3</magnitude>  
  6.         <updated>2010-09-26 06:44:37</updated>  
  7.         <link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/us2010brar.php</link>  
  8.         <latitude>-14.3009</latitude>  
  9.         <longitude>167.9491</longitude>  
  10.         <elev>-80100.0</elev>  
  11.     </entry>  
  12.     <entry>  
  13.         <!-- 還有entry條目,省略-->  
  14.     </entry>  
  15. </feed>  

<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><feed number="25"> <entry> <title>Vanuatu</title> <magnitude>5.3</magnitude> <updated>2010-09-26 06:44:37</updated> <link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/us2010brar.php</link> <latitude>-14.3009</latitude> <longitude>167.9491</longitude> <elev>-80100.0</elev> </entry> <entry> <!-- 還有entry條目,省略--> </entry></feed>

就是我們解析獲得的所有地震條目,并且其中的各個元素及其内容、屬性等按我們在SerializeEarthquakeHandler中指定的組織方式儲存。

三.總結

在這塊内容中我們學習了Android平台上建立XML的方法,從以上的Demo例子中我們可以發現Android上不僅解析XML方式多,并且友善,而且建立XML也是很友善直覺,好了解和實作的。

到這塊為止,我們就學習完了Android平台上和XML相關的内容,包括解析和建立XML等和XML相關的讀與寫兩個方面,有了這些基礎,我想處理Android上的XML文檔等基本可以輕松應付了,希望以上的學習内容對你也有所幫助,感謝你一直的關注!

注:

參考資料:http://www.ibm.com/developerworks/cn/xml/x-android/