天天看點

Android中XML解析-PULL解析

前面寫了兩篇XML解析的Dom和SAX方式,Dom比較符合思維方式,SAX事件驅動注重效率,除了這兩種方式以外也可以使用Android内置的Pull解析器解析XML檔案。 Pull解析器的運作方式與 SAX 解析器相似,也是事件觸發的。Pull解析方式讓應用程式完全控制文檔該怎麼樣被解析,比如開始和結束元素事件,使用parser.next()可以進入下一個元素并觸發相應事件。通過Parser.getEventType()方法來取得事件的代碼值,解析是在開始時就完成了大部分處理。事件将作為數值代碼被發送,是以可以使用一個switch對感興趣的事件進行處理,隻過PULL方式讀xml回調方法傳回的是數字。

建立XML先執行個體化一個序列化對象,之後的通過Tag進行操作:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

<code>public</code> <code>void</code> <code>createXML() {</code>

<code>        </code><code>// 初始化一個序列化對象</code>

<code>        </code><code>XmlSerializer serializer = Xml.newSerializer();</code>

<code>        </code><code>File path = </code><code>new</code> <code>File(getFilesDir(), </code><code>"BookTest.xml"</code><code>);</code>

<code>        </code><code>try</code> <code>{</code>

<code>            </code><code>FileOutputStream foStream = </code><code>new</code> <code>FileOutputStream(path);</code>

<code>            </code><code>serializer.setOutput(foStream, </code><code>"utf-8"</code><code>);</code>

<code>            </code><code>//設定文檔&lt;?xml version='1.0' encoding='utf-8' standalone='yes'?&gt;</code>

<code>            </code><code>serializer.startDocument(</code><code>"utf-8"</code><code>, </code><code>true</code><code>);</code>

<code>            </code><code>//設定根節點</code>

<code>            </code><code>serializer.startTag(</code><code>null</code><code>, </code><code>"Books"</code><code>);</code>

<code>            </code><code>for</code> <code>(</code><code>int</code> <code>i = </code><code>1</code><code>; i &lt; </code><code>4</code><code>; i++) {</code>

<code>                </code><code>//設定子節點</code>

<code>                </code><code>serializer.startTag(</code><code>null</code><code>, </code><code>"Book"</code><code>);</code>

<code>                </code><code>serializer.attribute(</code><code>null</code><code>, </code><code>"name"</code><code>, </code><code>"書籍"</code> <code>+ i);</code>

<code>                </code><code>serializer.startTag(</code><code>null</code><code>, </code><code>"Title"</code><code>);</code>

<code>                </code><code>serializer.text(</code><code>"内容"</code> <code>+ i);</code>

<code>                </code><code>serializer.endTag(</code><code>null</code><code>, </code><code>"Title"</code><code>);</code>

<code>                </code><code>serializer.endTag(</code><code>null</code><code>, </code><code>"Book"</code><code>);</code>

<code>            </code><code>}</code>

<code>            </code><code>serializer.endTag(</code><code>null</code><code>, </code><code>"Books"</code><code>);</code>

<code>            </code><code>serializer.endDocument();</code>

<code>        </code><code>} </code><code>catch</code> <code>(FileNotFoundException e) {</code>

<code>            </code><code>// TODO Auto-generated catch block</code>

<code>            </code><code>e.printStackTrace();</code>

<code>        </code><code>} </code><code>catch</code> <code>(IllegalArgumentException e) {</code>

<code>        </code><code>} </code><code>catch</code> <code>(IllegalStateException e) {</code>

<code>        </code><code>} </code><code>catch</code> <code>(IOException e) {</code>

<code>        </code><code>}</code>

<code>    </code><code>}</code>

 生成的XML的結果:

<code>&lt;?xml version=</code><code>'1.0'</code> <code>encoding=</code><code>'utf-8'</code> <code>standalone=</code><code>'yes'</code><code>?&gt;</code>

<code>&lt;Books&gt;</code>

<code>    </code><code>&lt;Book name=</code><code>"書籍1"</code> <code>&gt;</code>

<code>        </code><code>&lt;Title&gt;</code>

<code>内容</code><code>1</code>

<code>        </code><code>&lt;/Title&gt;</code>

<code>    </code><code>&lt;/Book&gt;</code>

<code>    </code><code>&lt;Book name=</code><code>"書籍2"</code> <code>&gt;</code>

<code>内容</code><code>2</code>

<code>    </code><code>&lt;Book name=</code><code>"書籍3"</code> <code>&gt;</code>

<code>内容</code><code>3</code>

<code>&lt;/Books&gt;</code>

首先看一張效果圖:

Android中XML解析-PULL解析

展示内容調用getListBooksByPull方法:

38

39

40

41

42

43

44

<code>public</code> <code>List&lt;Book&gt; getListBooksByPull() {</code>

<code>    </code><code>list = </code><code>new</code> <code>ArrayList&lt;Book&gt;();</code>

<code>    </code><code>File path = </code><code>new</code> <code>File(getFilesDir(), </code><code>"BookTest.xml"</code><code>);</code>

<code>    </code><code>try</code> <code>{</code>

<code>        </code><code>FileInputStream inputStream = </code><code>new</code> <code>FileInputStream(path);</code>

<code>        </code><code>// 獲得pull解析器對象</code>

<code>        </code><code>XmlPullParser parser = Xml.newPullParser();</code>

<code>        </code><code>// 指定解析的檔案和編碼格式</code>

<code>        </code><code>parser.setInput(inputStream, </code><code>"utf-8"</code><code>);</code>

<code>        </code><code>int</code> <code>eventType = parser.getEventType(); </code><code>// 獲得事件類型</code>

<code>        </code><code>Book book = </code><code>null</code><code>;</code>

<code>        </code><code>while</code> <code>(eventType != XmlPullParser.END_DOCUMENT) {</code>

<code>            </code><code>String tagNameString = parser.getName();</code>

<code>            </code><code>switch</code> <code>(eventType) {</code>

<code>            </code><code>case</code> <code>XmlPullParser.START_TAG:</code>

<code>                </code><code>if</code> <code>(</code><code>"Book"</code><code>.equals(tagNameString)) {</code><code>//Book标簽</code>

<code>                    </code><code>book = </code><code>new</code> <code>Book();</code>

<code>                    </code><code>book.setName(parser.getAttributeValue(</code><code>null</code><code>, </code><code>"name"</code><code>));</code>

<code>                </code><code>} </code><code>else</code> <code>if</code> <code>(</code><code>"Title"</code><code>.equals(tagNameString)) {</code><code>//Title标簽</code>

<code>                    </code><code>book.setTitle(parser.nextText());</code>

<code>                </code><code>}</code>

<code>                </code><code>break</code><code>;</code>

<code>            </code><code>case</code> <code>XmlPullParser.END_TAG:</code>

<code>                </code><code>if</code> <code>(</code><code>"Book"</code><code>.equals(tagNameString)) {</code>

<code>                    </code><code>list.add(book);</code>

<code>            </code><code>default</code><code>:</code>

<code>            </code><code>eventType = parser.next();</code><code>//重新指派,不然會死循環</code>

<code>    </code><code>} </code><code>catch</code> <code>(FileNotFoundException e) {</code>

<code>        </code><code>// TODO Auto-generated catch block</code>

<code>        </code><code>e.printStackTrace();</code>

<code>    </code><code>} </code><code>catch</code> <code>(XmlPullParserException e) {</code>

<code>    </code><code>} </code><code>catch</code> <code>(IOException e) {</code>

<code>    </code><code>return</code> <code>list;</code>

<code>}</code>

 相對于Dom和SAX來說,Pull比較簡單易讀,不過簡單的總結一下常用的幾個方法:讀取到xml的聲明傳回      START_DOCUMENT; 讀取到xml的結束傳回       END_DOCUMENT ; 讀取到xml的開始标簽傳回 START_TAG ,讀取到xml的結束标簽傳回 END_TAG 讀取到xml的文本傳回       TEXT .

Activity加載時候調用:

<code>ListView listView = (ListView) findViewById(R.id.list_pull);</code>

<code>    </code><code>ArrayList&lt;HashMap&lt;String, String&gt;&gt; arrayList = </code><code>new</code> <code>ArrayList&lt;HashMap&lt;String, String&gt;&gt;();</code>

<code>    </code><code>list = getListBooksByPull();</code>

<code>    </code><code>for</code> <code>(Book book : list) {</code>

<code>        </code><code>HashMap&lt;String, String&gt; map = </code><code>new</code> <code>HashMap&lt;String, String&gt;();</code>

<code>        </code><code>map.put(</code><code>"itemTitle"</code><code>, book.getName());</code>

<code>        </code><code>map.put(</code><code>"itemText"</code><code>, book.getTitle());</code>

<code>        </code><code>arrayList.add(map);</code>

<code>    </code><code>SimpleAdapter simpleAdapter = </code><code>new</code> <code>SimpleAdapter(</code><code>this</code><code>, arrayList,</code>

<code>            </code><code>R.layout.book, </code><code>new</code> <code>String[] { </code><code>"itemTitle"</code><code>, </code><code>"itemText"</code> <code>},</code>

<code>            </code><code>new</code> <code>int</code><code>[] { R.id.itemTitle, R.id.itemText });</code>

<code>    </code><code>listView.setAdapter(simpleAdapter);</code>

  簡單回顧一下三種解析方式,Dom解析xml是先把xml文檔都讀到記憶體中,然後再用DOM API來通路樹形結構,并擷取資料。這個寫起來很簡單,但是很消耗記憶體。要是資料過大,手機配置不行可能會當機。SAX解析是對文檔進行順序掃描,當掃描到文檔(document)開始與結束、元素(element)開始與結束、文檔(document)結束等地方時通知事件處理函數,由事件處理函數做相應動作,然後繼續同樣的掃描,直至文檔結束。Pull解析器和SAX解析器很相似,但SAX解析器的工作方式是自動将事件推入注冊的事件處理器進行處理,是以你不能控制事件的處理主動結束;而Pull解析器的工作方式為允許你的應用程式代碼主動從解析器中擷取事件,正因為是主動擷取事件,是以可以在滿足了需要的條件後不再擷取事件,結束解析。Pull的寫法确實很輕巧也很容易上手,個人比較喜歡Pull。

本文轉自Fly_Elephant部落格園部落格,原文連結:http://www.cnblogs.com/xiaofeixiang/p/4069483.html,如需轉載請自行聯系原作者

繼續閱讀