XML解析學習——創建XML

一.基礎知識
  在前面的學習過程中,我們基本上比較全面的學習了OPhone/Android平臺上讀取XML文檔的方法,介紹了使用Java SAX、OPhone/Android SAX、DOM和Pull等各種方式來讀取XML文檔內容。
  目前爲止,我們一直專注於解析已有的XML文檔,實際上我們也是需要讀XML的情形比較多。但是我們可能也有寫XML的需要,應用程序可能需要將 XML 發送到遠程服務器,或者需要以XML的形式保存數據等。因此在這部分內容中我們就來學習下OPhone/Android平臺上創建XML的方法。
  OPhone/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所示:

  圖1 創建XML


  首先解析USGS的地震數據並以ListView的方式顯示,然後點擊最上方的"Create XML"按鈕就會重新把解析獲得的地震數據重新創建爲一個XML文件。
  新建一個OPhone工程OPhoneXMLDemoSerialize。
  添加進之前Demo工程OPhoneXMLDemoSaxII中的EarthquakeEntry.java和OPhoneSaxEarthquakeHandler.java文件。如果需要從本地讀取xml數據的話,同時在assets文件夾下添加保存爲xml格式了的USGS地震數據USGS_Earthquake_1M2_5.xml,如果需要聯網讀取的話,在manifest.xml文件中添加權限:

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


  並修改res/layout下的main.xml爲:

  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>  


  接下來就來新建添加一個類SerializeEarthquakeHandler,用來創建XML,內容如下:

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


  在創建XML的方法中
   //寫Xml數據
   public String writeXml(ArrayList<EarthquakeEntry> earthquakeEntryList)
  首先創建XmlSerializer,
     //創建XmlSerializer,有兩種方式
     XmlPullParserFactory pullFactory;
     //方式一:使用工廠類XmlPullParserFactory的方式
     pullFactory = XmlPullParserFactory.newInstance();
     XmlSerializer xmlSerializer = pullFactory.newSerializer();
     //方式二:使用Android提供的實用工具類android.util.Xml
  //   XmlSerializer xmlSerializer = Xml.newSerializer();
  創建XmlSerializer有兩種方式,一種是使用我們介紹的org.xmlpull.v1包中的工廠類XmlPullParserFactory。除了這種方式外,還可以使用OPhone/Android SDK提供的實用工具包android.util中的類Xml的newSerializer()方法直接創建。
  接着爲XmlSerializer設置一個輸出的Writer,
  xmlSerializer.setOutput(xmlWriter);
  這裏將事件推送到了一個 java.io.StringWriter 實例中。
  然後就可以使用具體的startDocument開始文檔,endDocument結束文檔,startTag開始元素,endTag結束元素,text添加文本等方法來創建具體的XML文檔內容,具體方法參考上面的代碼部分。從代碼中我們可以看到,使用XmlSerializer創建XML還是相當直觀和方便的。
  最後添加OPhoneXMLDemoSerialize.java文件中的內容爲:

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


  程序前部分是使用OPhone/Android SAX的方式解析XML文檔,然後在按鈕的點擊回調函數中把解析獲得的地震數據重新創建爲XML文檔的形式,並分別用Log打印和保存爲文件。

  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.    });  


   完成了,可以保存運行看下效果。
  當點擊屏幕上方的"Create XML"按鈕時,程序就會創建一個形式更加簡單的XML文檔,同時在DDMS的LogCat裏打印出創建的XML文檔內容,如下圖2所示:

  圖2 Log打印出的創建的XML文檔內容

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

  圖3 保存着的創建出來的XML文件


  並且我們可以把這個文件導出到電腦上,可以看到裏面的內容爲:

  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>  


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

  三.總結
  在這塊內容中我們學習了OPhone/Android平臺上創建XML的方法,從以上的Demo例子中我們可以發現OPhone/Android上不僅解析XML方式多,並且方便,而且創建XML也是很方便直觀,好理解和實現的。
  到這塊爲止,我們就學習完了OPhone/Android平臺上和XML相關的內容,包括解析和創建XML等和XML相關的讀與寫兩個方面,有了這些基礎,我想處理OPhone/Android上的XML文檔等基本可以輕鬆應付了,希望以上的學習內容對你也有所幫助,感謝你一直的關注!

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章