iPhone解析非UTF-8的XML


/ Published in: iPhone
Save to your folder(s)



Copy this code and paste it in your HTML
  1. 做iPhone的网络应用,处理XML是家常便饭,NSXMLParser用起来还是得心应手的。不过这个东西,处理非UTF-8,会解析失败。这篇文章就是想和大家一起分享一些这方面开发的新的。
  2.  
  3.  
  4.  
  5. 我们在某个RSS地址,可以得到下面这样的XML文件。我这里只是截取一段,
  6.  
  7.  
  8.  
  9. ---------------------------------------
  10.  
  11.  
  12. <?xml version="1.0" encoding="big5"?>
  13.  
  14. <rss version="2.0">
  15.  
  16. <channel>
  17.  
  18. <title>RTHK On Internet - 即 時 新 聞</title>
  19.  
  20. <link><![CDATA[http://www.rthk.org.hk/rthk/news/expressnews/]]></link>
  21.  
  22. <description>RTHK On Internet - 即 時 新 聞</description>
  23.  
  24. <pubDate>Sun, 11 Oct 2009 15:02:02 +0800</pubDate>
  25.  
  26.  
  27. <item>
  28.  
  29. <title><![CDATA[&#34910;生署要求浸會醫院4周內 就產婦死亡個案提交報告 ]]></title>
  30.  
  31. <link><![CDATA[http://www.rthk.org.hk/rthk/news/expressnews/20091011/news_20091011_55_618483.htm]]></link>
  32.  
  33. <description><![CDATA[
  34.  
  35. &#34910;生署昨晚已經收到浸會醫院通知,有一宗產婦死亡個案,浸會醫院需要在4星期內向&#34910;生署提交報告,案件亦交由死因庭跟進。
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43. &#34910;生署數字顯示,由07年至今年8月,共接獲97宗私家醫院醫療事故的通報。去年發生的事故中,最多的是進行手術或介入程序期間出現併發症,其次還有孕婦及產婦死亡,或與孕婦在分娩過程中,生產時,或產後出現嚴重併發症;部份則包括初生嬰兒出現死亡或嚴重受傷;錯誤為病人或身體部位進行外科或介入手術程序等。
  44.  
  45.  
  46.  
  47.  
  48.  
  49. ]]></description>
  50.  
  51. <pubDate>
  52.  
  53. Sun, 11 Oct 2009 14:50:46 +0800
  54.  
  55. </pubDate>
  56.  
  57. </item>
  58.  
  59.  
  60. </channel>
  61.  
  62. </rss>
  63.  
  64. ----------------------------------------
  65.  
  66. 这是一个很常用的RSS返回的XML,是繁体中文的,编码格式是big5。说编码格式是big5有两层意思:
  67.  
  68. [1] 网络流返回的NSData是big5编码的。所以这样的NSData送给NSXMLParser是不能正确解析的。
  69.  
  70. [2] 第一句话指明了XML文件也是用big5编码的。
  71.  
  72.  
  73.  
  74. 对应于上面两个问题,我的解决思路是:
  75.  
  76. [1] 把Big5编码的NSData转换成UTF-8编码的NSData
  77.  
  78. [2] 将第一行<?xml version="1.0" encoding="big5"?>转换成<?xml version="1.0" encoding="utf-8"?>
  79.  
  80.  
  81.  
  82. 第二个转换不难,只要我们有NSString对象。第一个转换要用到CFStringRef,代码如下:
  83.  
  84.  
  85. Cpp代码
  86. CFStringRef big5Str = CFStringCreateWithBytes(NULL,
  87. [inData bytes],
  88. [inData length],
  89. kCFStringEncodingBig5_HKSCS_1999,
  90. false); //[A]
  91. if (NULL == big5Str) {
  92. return nil;
  93. }
  94. else {
  95. NSString *big5NSString = (NSString *)big5Str;
  96. NSString *utf8NSString = [big5NSString stringByReplacingOccurrencesOfString:@"<?xml version=\"1.0\" encoding=\"big5\"?>"
  97. withString:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"]; //[B]
  98. return [utf8NSString dataUsingEncoding:NSUTF8StringEncoding]; //[C]
  99. }
  100.  
  101. CFStringRef big5Str = CFStringCreateWithBytes(NULL,
  102. [inData bytes],
  103. [inData length],
  104. kCFStringEncodingBig5_HKSCS_1999,
  105. false); //[A]
  106. if (NULL == big5Str) {
  107. return nil;
  108. }
  109. else {
  110. NSString *big5NSString = (NSString *)big5Str;
  111. NSString *utf8NSString = [big5NSString stringByReplacingOccurrencesOfString:@"<?xml version=\"1.0\" encoding=\"big5\"?>"
  112. withString:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"]; //[B]
  113. return [utf8NSString dataUsingEncoding:NSUTF8StringEncoding]; //[C]
  114. } 思路就是先把NSData转成CFStringRef的对象[A], 然后这个对象再转成UTF-8的NSData [C],这就解决了问题[1]
  115.  
  116. 中间的[B]就解决了问题[2]。这里要注意两个问题:
  117.  
  118. (1)如果你的XML编码是GBK,或者GB23120或者其他的,kCFStringEncodingBig5_HKSCS_1999要换成你对应的编码方式。
  119.  
  120. (2)如果你的XML编码也是big5的,也许kCFStringEncodingBig5_HKSCS_1999并不适合你的应用。因为对应big5的编码常量还有两种,他们是:
  121.  
  122. kCFStringEncodingBig5_E
  123.  
  124. kCFStringEncodingBig5。
  125.  
  126. 这个你可以查阅帮助文档,然后一个个试。
  127.  
  128.  
  129.  
  130. 然后把return的NSData送到NSXMLParser,就可以正确解析了。可是还没有结束,大家仔细看看XML文件里面还有&#34910这样的东西。这个是繁体中文”衛“字,我们如果不处理这个东西,显示给用户看得就是&#34910,这显然是不行的。这个其实也好办,只需要用下面这句话就可以把一个number转成NSString了:
  131.  
  132.  
  133. [NSString stringWithFormat:@"%C", number]
  134.  
  135. 这个number就是34910,是一个整数,十进制的整数(不是十六进制的)。到这里,整个处理过程就OK了,我们就可以正确得到Big5的RSS新闻了。因为这是一个客户项目,不过我可以给各小截图大家看看:

URL: http://www.javaeye.com/topic/493525

Report this snippet


Comments

RSS Icon Subscribe to comments

You need to login to post a comment.