添加了一個用於顯示的ListVIEw 控件。
接著添加androidXMLDemoSax.Java 文件的內容。
先添加獲取XML 數據源的方法:
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;
}
這是從 USGS的網站上讀取 XML 數據並以 InputStream 的形式返回。因為需要用到聯網功能,所以還得在 manifest.XML文件中添加聯網權限:
< uses-permission android:name = "android.permission.INTERNET" />
這是聯網獲取XML 數據,也可以從本地讀取 XML 數據,因為校園網會打不開 USGS 的網站,因此復制了一份 USGS 的地震數據以文件的形式保存在 assets 文件夾下,並使用如下函數讀取:
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;
}
有了XML 數據,就可以接下來進行解析了。
//獲取地震數據流
InputStream earthquakeStream = readEarthquakeDataFromFile();
//Sax方式進行XML解析
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
SAXParser parser = factory.newSAXParser();
SaxEarthquakeHandler saxHandler = new SaxEarthquakeHandler();
parser.parse(earthquakeStream, saxHandler);
//獲取解析後的列表數據
earthquakeEntryList = saxHandler.getEarthquakeEntryList();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
最後添加定義相關變量,用把解析的數據用ListVIEw 顯示:
//定義顯示的List相關變量
ListVIEw list;
ArrayAdapter<EarthquakeEntry> adapter;
ArrayList<EarthquakeEntry> earthquakeEntryList;
//用ListVIEw進行顯示
list = (ListView)this.findVIEwById(R.id.list);
adapter = new ArrayAdapter<EarthquakeEntry>(this, android.R.layout.simple_list_item_1, earthquakeEntryList);
list.setAdapter(adapter);
完成了,可以保存運行看下效果。
以上使用的是Javax.xml.parsers 包中的 SAXParser 來實現, SAXParser 包裝了底層的 XMLReader ,實現起來更加方便。但是我們也可以使用 XMLReader 來實現解析,下面就看下使用具體的 XMLReader 的方式,實現代碼如下所示:
//使用org.xml.sax包中的XMLReader進行XML解析
XMLReader XMLReader = null;
//獲取XMLReader的方式有兩種
//方式一:使用Javax.xml.parsers.SAXParser的getXMLReader()方法
// try {
// xmlReader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
// } catch (Exception e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
//方式二:使用org.xml.sax.helpers.XMLReaderFactory的createXMLReader()方法
try {
//設置系統的"org.xml.sax.driver",XMLReaderFactory創建createXMLReader()時要用到
System.setProperty("org.xml.sax.driver","org.XMLpull.v1.sax2.Driver");
xmlReader = XMLReaderFactory.createXMLReader();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
SaxEarthquakeHandler saxHandler = new SaxEarthquakeHandler();
XMLReader.setContentHandler(saxHandler);
//XMLReader的輸入為InputSource
InputSource inSource = new InputSource(earthquakeStream);
try {
XMLReader.parse(inSource);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//獲取解析後的列表數據
earthquakeEntryList = saxHandler.getEarthquakeEntryList();
其中獲取XMLReader 的方式有兩種,一種是先獲取 SAXParser ,然後通過 getXMLReader() 方法來獲取,
xmlReader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
另一種是直接使用XMLReader 的工廠類 XMLReaderFactory 調用 createXMLReader() 方法創建,
xmlReader = XMLReaderFactory. createXMLReader ();
但 不管是那種方式,只有獲得了XMLReader 實例,接下來的操作都是一樣的,先注冊文檔內容的事件處理器實例,
XMLReader.setContentHandler(saxHandler);
然後調用parse方法開始解析,
XMLReader.parse(inSource);
這樣就用XMLReader進行了XML解析。
四. 總結
在這部分中我們首先學習了Android 上和 XML 解析相關的各個包的簡單介紹,並且從有這麼多個相關的包我們可以知道 android 為 XML 的讀寫提供了相當大的支持。
然後具體學習了android 上使用 SAX 方式解析 XML 的基本知識,使用 Javax.xml.parsers 包中的 SAXParser 進行解析,及使用 org.xml.sax 包中的 XMLReader 進行解析兩種方式分別的步驟,最後用解析 USGS 地震數據的 Demo 例子來實現介紹的內容。
這部分介紹的SAX 方式是屬於原來 Java 就有的 XML 處理方式,同時, Android 平台為了使解析 XML 還能更加方便和更加健壯,提供了 android.sax 包來進行 SAX 進行 XML ,這部分內容我們以後我們繼續接著學習。
android XML解析學習――Sax方式(續)
一.基礎知識
在《Android XML解析學習――Sax方式》中我們學習了Android上使用Java的SAX進行XML解析的方式。而在android平台上使用SAX解析XML,除了使用Java的API外,還可以使用Android SDK帶的 ="EN-US">API來實現。Android SDK中和SAX解析相關的包為android.sax,在這個包中android提供了都有的SAX API,使用它們可以更加方便的進行SAX方式的XML解析。
當xml文件中在不同的位置處有相同的元素標簽名時,在相應的事件回調處理函數中往往就需要進行判斷處理。比如USGS的XML形式的地震數據為:
<?XML version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" XMLns:georss="http://www.georss.org/georss">
<updated>2010-09-15T04:41:18Z</updated>
<title>USGS M2.5+ Earthquakes</title>
<subtitle>Real-time, worldwide earthquake list for the past day</subtitle>
<link rel="self" href="http://earthquake.usgs.gov/earthquakes/catalogs/1day-M2.5.xml" mce_href="http://earthquake.usgs.gov/earthquakes/catalogs/1day-M2.5.XML"/>
<link href="http://earthquake.usgs.gov/earthquakes/" mce_href="http://earthquake.usgs.gov/earthquakes/"/>
<author><name>U.S. Geological Survey</name></author>
<id>http://earthquake.usgs.gov/</id>
<icon>/favicon.ico</icon>
<entry>
<id>urn:earthquake-usgs-gov:ak:10078833</id>
<title>M 2.9, Southern Alaska</title>
<updated>2010-09-15T04:14:03Z</updated>
<link rel="alternate" type="text/Html" href="http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/ak10078833.php" mce_href="http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/ak10078833.PHP"/>
<summary type="Html">
<!--[CDATA[<img src="http://earthquake.usgs.gov/images/globes/60_-155.jpg" mce_src="http://earthquake.usgs.gov/images/globes/60_-155.jpg" alt="59.909°N 153.124°W" align="left" hspace="20" /><p>Wednesday, September 15, 2010 04:14:03 UTC<br>Tuesday, September 14, 2010 08:14:03 PM at epicenter</p><p><strong>Depth</strong>: 98.90 km (61.45 mi)</p>]]-->
</summary>
<georss:point>59.9094 -153.1241</georss:point>
<georss:elev>-98900</georss:elev>
<category label="Age" term="Past hour"/>
</entry>
<entry>
<!-- 還有entry條目,省略-->
</entry>
</feed>
我們看到在<entry>開始前就有<updated>、<title>和<link>等元素標簽,而<entry></entry>元素中也包含這些標簽名,在SAX解析時都會產生相應的事件,但我們實際需要處理的為<entry></entry>元素中的這些標簽產生的事件,因此我們設置了一個變量
private Boolean startEntryElementFlag = false;
來進行判斷。對以上的xml數據來說,這樣的處理還不會出現問題,但是如果需要解析一個更加復雜的XML文檔,則類似的需要對不同位置處的相同標簽名進行判斷這樣的處理可能會帶來各種各樣的Bug。
而使用android.sax包中的API來進行SAX方式的解析則不會有以上的問題。實際上使用android.sax包還有點結合了我們以後會詳細介紹的DOM方式,首先獲取需要解析部分的根元素,然後使用getChild方法獲取具體的某個子元素,之後就可以為具體的元素設置事件處理的回調函數,比如為一個元素分別設置元素開始的事件處理setStartElementListener,元素包含的文本內容結束的事件處理setEndTextElementListener和元素結束的事件處理setEndElementListener。
概括的來說,android.sax包進行XML解析的過程為用DOM的方式獲取具體位置處的元素,然後為其設置需要的事件處理函數。具體的實現我們可以看實例開發部分的代碼。
Android SDK中提供的和XML相關的還有一個類:android.util.Xml,在該類中提供了比較實用的XML相關的類方法,比如開始解析的parse方法,和直接創建XmlPullParser及XMLSerializer(這兩塊內容以後介紹)的方法等。
下面我們就用上面介紹的android SDK中的SAX方式來實現解析XML形式的USGS地震數據的Demo例子。