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隔离存储空间
1 2 3 4 5 6 7 8 9 | string url = "http://www.google.com/ig/api?weather=guangzhou&hl=zh-cn" ;//&hl=zh-cn WebClient 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无效字符的方法:
1 2 3 4 5 | 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属性也没了,因此解析出错。这个问题不定时的出现,现在仅仅是实现了中文读取,今后需要在程序中加入相应的错误检测代码,否则解析 出错程序就会自动退出了。
这次编写程序对我的影响很深刻,看似很简单的一个应用却引出了那么多的问题,水很深啊水很深。。。不过最后成功了,非常开心,也增强了我的自信,遇到困难需要自己动手去查去学不管能不能解决问题最终都是肯定能有所收获的。