wp7的應用還是太少了,中文應用更少。雖然有天氣預報應用但是自己感覺並不好用,感覺這樣的程式應該很簡單,於是萌生了自己寫一個的想法。
印證了群裡朋友說的一句話:程式員往往都是使用別人的程式覺得這裡不好那裡不好,等到自己想做一個的時候才發現水很深。
整個過程真是幾經波折。先在網上搜尋一番,發現了Windows Phone 7 網路編程之天氣預報應用,看到xml解析的時候就知難而退了,因為在學校的時候學習xml無果。於是這個想法在我的onenote裡面待了很久,最近終於在工作上需要解析xml硬著頭皮瞭解了一下,其實並不是那麼難。於是開始動手做吧,先後又遇到了網路檔案無法直接調用,xml檔案讀取出來是亂碼等等問題,找了很多資料和文檔,現在終於實現了。
接下來說下程式的編寫過程:
我使用了LINQ to XML來解析xml檔案,在載入xml的時候最開始檔案路徑我直接填寫了http://www.google.com/ig/api?weather=guangzhou,報錯資訊大致是不能直接填寫web網路路徑。找了一下資料,HttpWebRequest相關的東西沒看明白,使用WebClient來擷取網路檔案資源。這裡參考了將網路資源寫入WP7隔離儲存空間
string url = "http://www.google.com/ig/api?weather=guangzhou&hl=zh-cn";//&hl=zh-cnWebClient wc = new WebClient();Uri uri = new Uri(url);wc.OpenReadAsync(uri, "api.xml");//第一種方法讀取網路資源,開啟流向指定資源的可讀流wc.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted);//讀取完成以後觸發的事件wc.DownloadStringAsync(uri, "api.xml");//第二種方法讀取網路資源,將指定的字串下載到指定的資源wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted);//讀取完成後觸發的事件
讀取完成後觸發事件的機制我並不瞭解,在這裡繞了很久的彎。我將對天氣對象的賦值操作寫在讀取完成的事件裡面,而對程式頁面上的TextBlock賦值顯示的語句寫在擷取網路資源語句之後,實際的執行順序是執行了擷取資源語句以後並沒有直接跳轉到讀取完成事件裡面的語句(因此天氣對象的值仍然是空的),直接執行了後面的TextBlock指派陳述式,最後才跳轉到讀取完成的事件裡面對天氣對象賦值。結果程式運行顯示的天氣為空白。這個事件還得詳細瞭解。
解決這個問題以後程式能夠順利運行並從網路更新資料了
但是接著問題就來了:在電腦上訪問http://www.google.com/ig/api?weather=guangzhou返回的xml檔案是中文的,Windows Phone 7 網路編程之天氣預報應用的作者也提到,在WP7中訪問這個介面返回的xml檔案是英文的,圖中可以看到最高溫度和最低溫度都是華氏溫度單位。評論中有人提到增加&hl=zh-cn以後返回的就是中文,我修改了程式中的相應地址以後,程式變成了這樣:
中文部分全都變成了亂碼!!!在網上搜尋了一下找到了問題所在
返回的XML的頭部,<?xml version="1.0" ?>,跟標準的XML頭部相比缺少了類似encoding=UTF-8這樣的編碼聲明。於是懷疑正是由於這一點導致SAX或者DOM解析器把本不是UTF-8的字元編碼當作UTF-8來處理,於是導致了亂碼和異常。經過google搜尋證實當使用hl=zh-cn時返回的是GBK編碼的XML,並且有許多用到這個API的php代碼都做了GBK->UTF-8的轉換處理。
問題到了這裡其實就很簡單了,既然是GBK編碼SAX和DOM預設當UTF-8來處理,並且我們不可能去更改GOOGLE的Servlet讓他返回一個在XML頭部帶encoding=GBK的XML。那麼我們只有兩個辦法,要嘛就把返回的XML從GBK編碼轉碼到UTF-8,要嘛就讓SAX和DOM解析器把XML當GBK來處理。
雖然是不同的平台,但也有相通的地方啊~~雖然找到了問題所在,但是解決方案可不那麼簡單了,搜尋了很久都說wp7不支援GBK編碼,找了幾個轉碼的方法也運行不了,MSDN上說只支援utf8和utf16。就要放棄了,已經在考慮天氣預報也就那幾個資料,自己寫個判斷晴天多雲的用中文顯示算了。這時候群裡的朋友給了一個類,能夠讓Silverlight支援GB2312中文編碼!用上以後在調試的過程中終於能在VS裡面看到string對象的內容變成中文了。
最後將包含中文xml資訊的string對象傳到xml解析方法的時候報出了'.', hexadecimal value 0x00, is an invalid character.錯誤,看來GBK支援類並不完美。於是繼續尋找解決方案,原因是由於string包含有無效字元,已經是焦頭爛額了。
找了幾個方法都會將中文和無效字元一起去掉,並最後找到了一個C#去除xml無效字元的方法:
public string CleanInvalidXmlChars(string text){ string re = @"[^\x0D\x20-\xD7FF\xE000-\xFFFD\x10000-x10FFFF\u4e00-\u9fa5]"; return System.Text.RegularExpressions.Regex.Replace(text, re, "");}
最終成功傳入中文xml資料,程式運行正常!
另外在偵錯工具的過程中偶爾不定時的會出現xml解析錯誤的情況,xml解析方法已經寫好了本該不會出錯,經過排查發現是google的問題,下面的xml是我在同一時間擷取的兩個不同城市的資料,廣州的xml檔案一切正常,貴陽xml檔案中框注的內容裡conditong的data屬性缺失了,相應的icon的data屬性也沒了,因此解析出錯。這個問題不定時的出現,現在僅僅是實現了中文讀取,今後需要在程式中加入相應的錯誤偵測代碼,否則解析出錯程式就會自動結束了。
這次編寫程式對我的影響很深刻,看似很簡單的一個應用卻引出了那麼多的問題,水很深啊水很深。。。不過最後成功了,非常開心,也增強了我的自信,遇到困難需要自己動手去查去學不管能不能解決問題最終都是肯定能有所收穫的。