一.基礎知識
在前面的學習過程中,我們基本上比較全面的學習了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文件中添加權限:
- <uses-permission android:name="android.permission.INTERNET" />
並修改res/layout下的main.xml爲:
- <?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,內容如下:
- 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,
//創建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文件中的內容爲:
- public class OPhoneXMLDemoSerialize 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;
- }
- }
程序前部分是使用OPhone/Android SAX的方式解析XML文檔,然後在按鈕的點擊回調函數中把解析獲得的地震數據重新創建爲XML文檔的形式,並分別用Log打印和保存爲文件。
- //點擊按鈕開始創建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所示:
圖2 Log打印出的創建的XML文檔內容
同時還會把創建的XML以文件的形式保存在系統中,我們可以在DDMS的File Explorer的data/data/com.ichliebephone.xml.serialize/files文件夾下看到,如下圖3所示:
圖3 保存着的創建出來的XML文件
並且我們可以把這個文件導出到電腦上,可以看到裏面的內容爲:
- <?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中指定的組織方式保存。
三.總結
在這塊內容中我們學習了OPhone/Android平臺上創建XML的方法,從以上的Demo例子中我們可以發現OPhone/Android上不僅解析XML方式多,並且方便,而且創建XML也是很方便直觀,好理解和實現的。
到這塊爲止,我們就學習完了OPhone/Android平臺上和XML相關的內容,包括解析和創建XML等和XML相關的讀與寫兩個方面,有了這些基礎,我想處理OPhone/Android上的XML文檔等基本可以輕鬆應付了,希望以上的學習內容對你也有所幫助,感謝你一直的關注!