歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Android基礎教程:SAX解析之錯誤糾正

Android基礎教程:SAX解析之錯誤糾正

日期:2017/3/1 10:55:33   编辑:Linux編程

在講這次錯誤之前,先看一下下面這段代碼。 【◆以下解析方法是錯誤的×】

  1. import java.util.ArrayList;
  2. import java.util.List;
  3. import org.xml.sax.Attributes;
  4. import org.xml.sax.SAXException;
  5. import org.xml.sax.helpers.DefaultHandler;
  6. import Android.util.Log;
  7. public class XmlHandler extends DefaultHandler{
  8. private final String TAG = this.getClass().getSimpleName();
  9. /**XML文件中標簽定義*/
  10. private final String TAG_Article = "Article";
  11. private final String TAG_ArticleID = "ArticleID";
  12. private final String TAG_Title = "Title";
  13. private final String TAG_Date = "Date";
  14. private final String TAG_SmallPictures = "SmallPictures";
  15. private final String TAG_LargePictures = "LargePictures";
  16. private final String TAG_Category = "Category";
  17. private static final String TAG_HeadNote = "HeadNote";
  18. private static final String TAG_SubTitle = "SubTitle";
  19. private static final String TAG_Source = "Source";
  20. //當前正在解析的TAG
  21. private String currentName;
  22. //單個文章
  23. private News news = null;
  24. //文章列表
  25. private List<News> newsList = null;
  26. //解析開始時間
  27. private long start_time;
  28. private boolean flag = false;
  29. @Override
  30. public void characters(char[] ch, int start, int length)
  31. throws SAXException {
  32. super.characters(ch, start, length);
  33. if(!flag) {
  34. return;
  35. }
  36. // 取值
  37. String value = new String(ch, start, length);
  38. Log.d(TAG, "Element: " + currentName + " Element Value: " + value);
  39. if(value != null) {
  40. if(TAG_ArticleID.equals(currentName)) {
  41. news.setArticleId(value);
  42. } else if(TAG_Title.equals(currentName)) {
  43. news.setTitle(value);
  44. } else if(TAG_Date.equals(currentName)) {
  45. news.setDate(value);
  46. } else if(TAG_Category.equals(currentName)) {
  47. news.setCategory(value);
  48. } else if(TAG_SmallPictures.equals(currentName)) {
  49. news.setSmallPicture(value);
  50. } else if(TAG_LargePictures.equals(currentName)) {
  51. news.setLargePicture(value);
  52. } else if(TAG_HeadNote.equals(currentName)) {
  53. news.setHeadNote(value);
  54. } else if(TAG_SubTitle.equals(currentName)) {
  55. news.setSubTitle(value);
  56. } else if(TAG_Source.equals(currentName)) {
  57. news.setSource(value);
  58. }
  59. }
  60. }
  61. @Override
  62. public void startDocument() throws SAXException {
  63. super.startDocument();
  64. start_time = System.currentTimeMillis();
  65. newsList = new ArrayList<News>();
  66. }
  67. @Override
  68. public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
  69. super.startElement(uri, localName, qName, attributes);
  70. this.currentName = localName;
  71. flag = true;
  72. if(TAG_Article.equals(localName)) {
  73. news = new News();
  74. }
  75. }
  76. @Override
  77. public void endElement(String uri, String localName, String qName)
  78. throws SAXException {
  79. super.endElement(uri, localName, qName);
  80. flag = false;
  81. if(TAG_Article.equals(localName)) {
  82. newsList.add(news);
  83. }
  84. }
  85. @Override
  86. public void endDocument() throws SAXException {
  87. super.endDocument();
  88. long end = System.currentTimeMillis();
  89. Log.d(TAG, "Parse List's Xml Cost: " + (end - start_time) + " !!");
  90. }
  91. }
Baidu 或者 Google 一下 “Android Sax 解析” , 給出的Sample無一例外都是如此。 坑爹啊... 甚至連有些書籍中都是這麼寫的, 比如《Android開發入門與實踐》 下載見 http://www.linuxidc.com/Linux/2011-11/48183.htm 。(本書親自確認過,其他書情況不詳)

沒錯, 一般情況下,這麼寫是可以的, 而且在大多數情況下解析出來也是正確的。 但是就是偶爾會出錯, 這個時候通常你都莫不著頭腦, 怎麼回事? 數據沒錯啊,解析部分代碼貌似也沒問題.. 真是奇了怪了。 其實問題都出在上面那段代碼上!!


大家都認為 SAX 解析過程大致如下:

startDocument -> startElement -> characters -> endElement -> endDocument


沒錯,就是這樣, startElement 讀取起始標簽, endElement 讀取結束標簽,characters 呢?當然是讀取其值, 這沒錯,但是大家都天真的以為 characters 只執行一次,並且一次就讀取了全部內容。錯就錯在這!


其實characters 是很有可能會執行多次的,當遇到內容中有回車,\t等等內容時,它很有可能就執行多次。 有的人可能會說,那我沒有這些是不是就只執行一次了? 看下我實測結果:



測試用XML如下:

  1. <News>
  2. <Article>
  3. <ArticleID>1000555</ArticleID>
  4. <Title><![CDATA[ 鄭州“亞洲第一橋”通車6年成危橋 ]]></Title>
  5. <Date>2011-11-25 14:23:52</Date>
  6. <SmallPictures>livenews/images/s20.png</SmallPictures>
  7. <LargePictures>livenews/images/l20.png</LargePictures>
  8. <Category>聞天下</Category>
  9. <HeadNote></HeadNote>
  10. <SubTitle></SubTitle>
  11. <Author></Author>
  12. <Source>人民日報</Source>
  13. <Abstract></Abstract>
  14. </Article>
  15. <Article>
  16. <ArticleID>1000554</ArticleID>
  17. <Title><![CDATA[ 內地事業單位擬設統一工資制度 ]]></Title>
  18. <Date>2011-11-25 14:22:33</Date>
  19. <Category><![CDATA[ 聞天下 ]]></Category>
  20. <HeadNote></HeadNote>
  21. <SubTitle></SubTitle>
  22. <Author></Author>
  23. <Source></Source>
  24. <Abstract></Abstract>
  25. </Article>
  26. <Article>
  27. <ArticleID>1000553</ArticleID>
  28. <Title></Title>
  29. <Date>2011-11-25 14:21:23</Date>
  30. <SmallPictures>livenews/images/s21.png</SmallPictures>
  31. <LargePictures>livenews/images/l21.png</LargePictures>
  32. <Category><![CDATA[ 星娛樂 ]]></Category>
  33. <HeadNote></HeadNote>
  34. <SubTitle></SubTitle>
  35. <Author></Author>
  36. <Source><![CDATA[ 鳳凰網綜合 ]]></Source>
  37. <Abstract></Abstract>
  38. </Article>
  39. <News>
Copyright © Linux教程網 All Rights Reserved