歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

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

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

  1. import java.util.ArrayList;  
  2. import java.util.List;  
  3.   
  4. import org.xml.sax.Attributes;  
  5. import org.xml.sax.SAXException;  
  6. import org.xml.sax.helpers.DefaultHandler;  
  7.   
  8. import Android.util.Log;  
  9.   
  10. public class XmlHandler extends DefaultHandler{  
  11.       
  12.     private final String TAG = this.getClass().getSimpleName();  
  13.       
  14.     /**XML文件中標簽定義*/  
  15.     private final String TAG_Article = "Article";  
  16.     private final String TAG_ArticleID = "ArticleID";  
  17.     private final String TAG_Title = "Title";  
  18.     private final String TAG_Date = "Date";  
  19.     private final String TAG_SmallPictures = "SmallPictures";  
  20.     private final String TAG_LargePictures = "LargePictures";  
  21.     private final String TAG_Category = "Category";  
  22.     private static final String TAG_HeadNote = "HeadNote";  
  23.     private static final String TAG_SubTitle = "SubTitle";  
  24.     private static final String TAG_Source = "Source";  
  25.       
  26.     //當前正在解析的TAG   
  27.     private String currentName;  
  28.       
  29.     //單個文章   
  30.     private News news = null;  
  31.       
  32.     //文章列表   
  33.     private List<News>  newsList = null;  
  34.       
  35.     //解析開始時間   
  36.     private long start_time;  
  37.       
  38.     private boolean flag = false;  
  39.       
  40.     @Override  
  41.     public void characters(char[] ch, int start, int length)  
  42.             throws SAXException {  
  43.         super.characters(ch, start, length);  
  44.           
  45.         if(!flag) {  
  46.             return;  
  47.         }  
  48.         // 取值   
  49.         String value = new String(ch, start, length);  
  50.         Log.d(TAG, "Element: " + currentName  + " Element Value: " + value);  
  51.         if(value != null) {  
  52.             if(TAG_ArticleID.equals(currentName)) {  
  53.                 news.setArticleId(value);  
  54.             } else if(TAG_Title.equals(currentName)) {  
  55.                 news.setTitle(value);  
  56.             } else if(TAG_Date.equals(currentName)) {  
  57.                 news.setDate(value);  
  58.             } else if(TAG_Category.equals(currentName)) {  
  59.                 news.setCategory(value);  
  60.             } else if(TAG_SmallPictures.equals(currentName)) {  
  61.                 news.setSmallPicture(value);  
  62.             } else if(TAG_LargePictures.equals(currentName)) {  
  63.                 news.setLargePicture(value);  
  64.             } else if(TAG_HeadNote.equals(currentName)) {  
  65.                 news.setHeadNote(value);  
  66.             } else if(TAG_SubTitle.equals(currentName)) {  
  67.                 news.setSubTitle(value);  
  68.             } else if(TAG_Source.equals(currentName)) {  
  69.                 news.setSource(value);  
  70.             }  
  71.         }  
  72.     }  
  73.   
  74.     @Override  
  75.     public void startDocument() throws SAXException {  
  76.         super.startDocument();  
  77.           
  78.         start_time = System.currentTimeMillis();  
  79.         newsList = new ArrayList<News>();  
  80.     }  
  81.   
  82.     @Override  
  83.     public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {  
  84.         super.startElement(uri, localName, qName, attributes);  
  85.         this.currentName = localName;  
  86.         flag = true;  
  87.         if(TAG_Article.equals(localName)) {  
  88.             news = new News();  
  89.         }  
  90.     }  
  91.       
  92.     @Override  
  93.     public void endElement(String uri, String localName, String qName)  
  94.             throws SAXException {  
  95.         super.endElement(uri, localName, qName);  
  96.         flag = false;  
  97.           
  98.         if(TAG_Article.equals(localName)) {  
  99.             newsList.add(news);  
  100.         }  
  101.     }  
  102.       
  103.     @Override  
  104.     public void endDocument() throws SAXException {  
  105.         super.endDocument();  
  106.           
  107.         long end = System.currentTimeMillis();  
  108.         Log.d(TAG, "Parse List's Xml Cost: " + (end - start_time) + " !!");  
  109.     }  
  110. }  
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