最終
代碼結構圖:
代碼詳解:
main.xml
<?xml version="1.0" encoding="utf-8"?><br /><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br /> android:orientation="vertical"<br /> android:layout_width="fill_parent"<br /> android:layout_height="fill_parent"<br /> ><br /><TextView<br /> android:layout_width="fill_parent"<br /> android:layout_height="wrap_content"<br /> android:id="@+id/textView"<br /> /><br /></LinearLayout><br />
beauties.xml
<?xml version="1.0" encoding="utf-8"?><br /><beauties ><br /><beauty><br /><name>林志玲</name><br /><age>28</age><br /></beauty><br /><beauty><br /><name>楊冪</name><br /><age>23</age><br /></beauty></p><p></beauties>
activity的代碼
package cn.com.sax;</p><p>import java.io.InputStream;<br />import java.util.ArrayList;</p><p>import javax.xml.parsers.SAXParser;<br />import javax.xml.parsers.SAXParserFactory;</p><p>import org.xml.sax.Attributes;<br />import org.xml.sax.InputSource;<br />import org.xml.sax.XMLReader;<br />import org.xml.sax.helpers.XMLReaderFactory;</p><p>import android.app.Activity;<br />import android.os.Bundle;<br />import android.sax.Element;<br />import android.sax.EndElementListener;<br />import android.sax.EndTextElementListener;<br />import android.sax.RootElement;<br />import android.sax.StartElementListener;<br />import android.util.Log;<br />import android.util.Xml;<br />import android.widget.TextView;<br />/**<br /> * @author chenzheng_java<br /> * @description 使用android.sax包下的類進行sax解析<br /> */<br />public class AndroidSaxActivity extends Activity {<br />private String result = "最終結果:/n";<br />private ArrayList<Beauty> beautyList = new ArrayList<Beauty>();<br />private Beauty beauty = null ;<br /> @Override<br /> public void onCreate(Bundle savedInstanceState) {<br /> super.onCreate(savedInstanceState);<br /> setContentView(R.layout.main);</p><p> /*以下XMLReader的這種解析方式也是屬於sax解析,<br /> * 同我們使用SaxParser功能一樣。但是這種功能更加的強大.<br /> */<br /> try {<br /> Log.i("通知", "開始解析");<br /> InputStream inputStream = this.getClassLoader().getResourceAsStream("beauties.xml");<br />SAXParserFactory factory = SAXParserFactory.newInstance();<br />SAXParser parser = factory.newSAXParser();<br />XMLReader reader = parser.getXMLReader();<br />reader.setContentHandler(getRootElement().getContentHandler());<br />reader.parse(new InputSource(inputStream));<br />Log.i("通知", "解析完畢");<br />} catch (Exception e) {<br />e.printStackTrace();<br />}</p><p>for(Beauty beauty:beautyList){<br />result+=beauty.toString()+"/n";</p><p>}</p><p>TextView textView = (TextView) this.findViewById(R.id.textView);<br />textView.setText(result);</p><p> }<br /> /**<br /> *<br /> * @return 返回設定好處理機制的rootElement<br /> */<br /> private RootElement getRootElement(){</p><p> /*rootElement代表著根節點,參數為根節點的tagName*/<br /> RootElement rootElement = new RootElement("beauties");<br /> /*擷取一類子節點,並為其設定相應的事件<br /> * 這裡需要注意,雖然我們只設定了一次beauty的事件,但是我們文檔中根節點下的所有<br /> * beauty卻都可以觸發這個事件。<br /> * */<br /> Element beautyElement = rootElement.getChild("beauty");<br /> // 讀到元素開始位置時觸發,如讀到<beauty>時<br /> beautyElement.setStartElementListener(new StartElementListener() {<br />@Override<br />public void start(Attributes attributes) {<br />Log.i("通知", "start");<br />beauty = new Beauty();<br />}<br />});<br /> //讀到元素結束位置時觸發,如讀到</beauty>時<br /> beautyElement.setEndElementListener(new EndElementListener() {<br />@Override<br />public void end() {<br />beautyList.add(beauty);<br />}<br />});</p><p> Element nameElement = beautyElement.getChild("name");<br /> // 讀到文本的末尾時觸發,這裡的body即為文本的內容部分<br /> nameElement.setEndTextElementListener(new EndTextElementListener() {<br />@Override<br />public void end(String body) {<br />beauty.setName(body);<br />}<br />});</p><p> Element ageElement = beautyElement.getChild("age");<br /> ageElement.setEndTextElementListener(new EndTextElementListener() {<br />@Override<br />public void end(String body) {<br />beauty.setAge(body);<br />}<br />});<br /> return rootElement;</p><p> }</p><p> private class Beauty {<br /> String name;<br /> String age;<br />public String getName() {<br />return name;<br />}<br />public void setName(String name) {<br />this.name = name;<br />}<br />public String getAge() {<br />return age;<br />}<br />public void setAge(String age) {<br />this.age = age;<br />}<br />@Override<br />public String toString() {<br />return "美女資料 [年齡=" + age + ", 姓名=" + name + "]";<br />}</p><p> }<br />}
運行便可以得到上面的代碼。
------------------------------------------
這裡我們來談一下,android為我們提供的一些和解析xml有關的類。
android.sax包。下面類和介面的主要結構
類主要有兩個,Element和RootElement。這裡大家一定要注意的一點是,在使用類的時候一定要看準你匯入的是什麼包,千萬不要倒錯包哦,否則你就等著在痛苦和鬱悶中死去吧。
其中RootElement是繼承自Element類的,只是用來代表document的根節點。它的方法基本上都是繼承自Element類的。它只定義了一個方法getContentHandler() ,該方法返回一個sax的contentHandler對象。
(這裡估計有人迷糊了,sax解析不是事件驅動模式嗎,怎麼還跟dom中才有的根節點扯上關係了。其實答案很簡單,最底層還是按照sax的方式進行解析的,這裡只是為了方便使用者使用,android才提供了這麼幾個類似和節點有關的方法,讓我們可以用節點的思維去操作sax解析,畢竟節點用起來條理性要比sax的事件驅動有條理性多了)。
Element類的主要方法有
其他的都沒什麼可說的,我就說一下getChild方法和requireChild方法的區別和聯絡,倆個方法都是通過tagName(標籤名)擷取當前element元素的子項目的。在原始碼中,requireChild是這樣實現的 public Element requireChild(String uri, String localName) {<br /> Element child = getChild(uri, localName);</p><p> if (requiredChilden == null) {<br /> requiredChilden = new ArrayList<Element>();<br /> requiredChilden.add(child);<br /> } else {<br /> if (!requiredChilden.contains(child)) {<br /> requiredChilden.add(child);<br /> }<br /> }</p><p> return child;<br /> }
其中requiredChilden是一個arrayList<Element>,這裡面存放著所有你訪問過的元素。這兩者最大的區別就是,當我們使用requireChild方法時,在我們解析的過程中,如果某一個訪問過的Element突然消失了(鬼知道是什麼原因),該方法會通過拋出異常的方式通知使用者。
------------------------------------------------------------------------
從代碼中我們可以看到,我們通過設定RootElement以及其子節點的事件監聽器,來規定解析xml時應該執行的操作;然後通過getContentHandler方法可以擷取一個ContentHandler對象。然後通過xmlreader的setContentHandler方法將其與解析器關聯起來。
------------------------------------------------------------------------
其實,這裡我們還可以用這樣的語句來進行解析Xml.parse(inputStream, Xml.Encoding.UTF_8, getRootElement().getContentHandler());這個XML類是android為我們提供的協助類。在後面我們將詳細的介紹。
------------------------------------------------------------------------
我們都知道通過SAXParser對象解析xml的方式,這裡我們又從代碼中看到了利用另一個對象XMLReader進行解析,那麼兩者到底有什麼聯絡和區別呢?
其實SAXParser是在SAX 1.0 定義的,而XMLReader則是在2.0中才開始出現的。你可以認為XMLReader的出現是為了替代SAXParser解析的,兩者本質上乾的事情是一樣的,只不過XMLReader的功能更加的強悍而已。
關於XMLReader的擷取方式,除了通過SAXParser的getXMLReader方法獲得之外,我們還可以通過以下兩種方式。
XMLReader parser=XMLReaderFactory.createXMLReader(); (1)
XMLReader parser=XMLReaderFactory.createXMLReader(String className); (2)
下面附上一段介紹:
In fact,XMLReader is an interface,so XMLReaderFactory needs a concrete class which implements this interface to get an instance,once the factory get the class's name ,then it use java reflection to create an instantiated object and return it,org.apache.xerces.parsers.SAXParser is such a class in case.</p><p>if you try to use api (1) to get an XMLReader instance, XMLReaderFactory first try to get the XMLReader's classname by retrieving the system property with key "org.xml.sax.driver", if this property has set with an appropriate classname,the factory use this name instantiated an object and return; if this property not set,then it fallback to class ParserFactory, ParserFactory then retrieves a system property named "org.xml.sax.parser" to get a parser's classname to instantiate ,if this property is not set too,your invocation to get a XMLreader will fail and a SAXException with the message "System property org.xml.sax.driver not specified" is throwed,otherwise,the ParserFactory will return an parser instance with the specified parser name to XMLReaderFactory,and XMLReaderFactory use this parser to instantiate an ParserAdapter like new ParserAdapter(parser), so the XMLReader you get is an instance of the classnew ParserAdapter.</p><p>so,in conclusion,in order to make it works as fine as you expected,you can do as the following ways to get an XMLReader:<br />(1)<br />XMLReader parser=XMLReaderFactory.createXMLReader(String className);<br />(2)<br />System.setProperty("org.xml.sax.driver","org.apache.xerces.parsers.SAXParser");<br />XMLReader parser=XMLReaderFactory.createXMLReader();<br />(3)<br />System.setProperty("org.xml.sax.parser","org.apache.xerces.parsers.SAXParser");<br />XMLReader parser=XMLReaderFactory.createXMLReader();<br />(4) more directly<br />XMLReader parser=new org.apache.xerces.parsers.SAXParser();<br /> 翻譯如下:
事實上,XMLReader是一個介面,所以想要產生一個XMLReader對象的話,我們的XMLReaderFactory需要關聯一個實現了該介面的類。XMLReaderFactory一旦獲得了實現了該介面的那個類的名稱,就會通過java的反射機制建立一個XMLReader對象返回給我們。
實際上,org.apache.xerces.parsers.SAXParser 就是一個滿足了這些條件的類。
如果你想通過XMLReader parser=XMLReaderFactory.createXMLReader(String className); 的方式獲得一個XMLReader對象,XMLReaderFactory 首先會先去系統的property中尋找名稱為"org.xml.sax.driver"的屬性,如果該屬性存在,則以該屬性的值作為classname去執行個體化一個XMLReader對象;如果該屬性沒有設定,則跳轉到ParserFactory這個類,通過訪問一個名稱為"org.xml.sax.parser"的系統變數來進行執行個體化;如果這個org.xml.sax.parser變數也沒有被設定,操作就會失敗然後跑出異常。如果org.xml.sax.parser存在,ParserFactory將會返回一個特定解析器的對象給XMLReaderFactory,XMLReaderFactory則通過得到的解析器對象去執行個體化一個PaserAdapter,所以從最底層看,我們得到的XMLReader對象就是一個PaserAdapter的對象。