2011-09-29 102 views
1

我正在將一個Android應用程序移植到iOS中,並且遇到了一個小障礙。我從網頁拉取HTML編碼的數據,但一些數據以Unicode顯示以顯示外來字符......所以在俄語(Летизамной)中的字符將被解析爲,"Лет..."將iOS HTML Unicode轉換爲NSString?

在android中,我是能夠通過調用HTML.fromHTML()來解決這個問題。 iOS中有類似的東西嗎?

+0

這裏有什麼問題?現在UTF-8非常普遍。您沒有提供任何關於HTML解析所使用的細節的信息,或者您真正遇到的問題。 –

+0

啊,你更新了。我認爲你的意思是數據是用HTML實體編碼的,但事實上並不包含HTML標籤? –

回答

6

編寫自己的HTML實體解碼器相當簡單。只需掃描字符串尋找&,閱讀以下內容;然後解釋結果。如果是「amp」,「lt」,「gt」或「quot」,則用相關字符替換它。如果它以#開頭,它是一個數字實體。如果#後面跟着「x」,則將其餘的爲十六進制,否則爲十進制。讀取數字,然後將字符插入到字符串中(如果您要寫入NSMutableString,則可以使用[str appendFormat:@"%C", thechar]. NSScanner可以使字符串掃描變得非常容易,尤其是因爲它已經知道如何讀取十六進制數字。我剛掀起了應該爲你做這個函數注意,我並沒有實際測試過這一點,所以你應該通過它的步伐運行它。

- (NSString *)stringByDecodingHTMLEntitiesInString:(NSString *)input { 
    NSMutableString *results = [NSMutableString string]; 
    NSScanner *scanner = [NSScanner scannerWithString:input]; 
    [scanner setCharactersToBeSkipped:nil]; 
    while (![scanner isAtEnd]) { 
     NSString *temp; 
     if ([scanner scanUpToString:@"&" intoString:&temp]) { 
      [results appendString:temp]; 
     } 
     if ([scanner scanString:@"&" intoString:NULL]) { 
      BOOL valid = YES; 
      unsigned c = 0; 
      NSUInteger savedLocation = [scanner scanLocation]; 
      if ([scanner scanString:@"#" intoString:NULL]) { 
       // it's a numeric entity 
       if ([scanner scanString:@"x" intoString:NULL]) { 
        // hexadecimal 
        unsigned int value; 
        if ([scanner scanHexInt:&value]) { 
         c = value; 
        } else { 
         valid = NO; 
        } 
       } else { 
        // decimal 
        int value; 
        if ([scanner scanInt:&value] && value >= 0) { 
         c = value; 
        } else { 
         valid = NO; 
        } 
       } 
       if (![scanner scanString:@";" intoString:NULL]) { 
        // not ;-terminated, bail out and emit the whole entity 
        valid = NO; 
       } 
      } else { 
       if (![scanner scanUpToString:@";" intoString:&temp]) { 
        // &; is not a valid entity 
        valid = NO; 
       } else if (![scanner scanString:@";" intoString:NULL]) { 
        // there was no trailing ; 
        valid = NO; 
       } else if ([temp isEqualToString:@"amp"]) { 
        c = '&'; 
       } else if ([temp isEqualToString:@"quot"]) { 
        c = '"'; 
       } else if ([temp isEqualToString:@"lt"]) { 
        c = '<'; 
       } else if ([temp isEqualToString:@"gt"]) { 
        c = '>'; 
       } else { 
        // unknown entity 
        valid = NO; 
       } 
      } 
      if (!valid) { 
       // we errored, just emit the whole thing raw 
       [results appendString:[input substringWithRange:NSMakeRange(savedLocation, [scanner scanLocation]-savedLocation)]]; 
      } else { 
       [results appendFormat:@"%C", c]; 
      } 
     } 
    } 
    return results; 
} 
+0

你的代碼失敗了,我不想嘗試修復它:P而是我研究了你的方法,顯然Google發佈了「Google Toolbox for Mac」(http://code.google.com/p/google-toolbox -for-mac /),其中包含一些有用的功能,可以完成我想要實現的功能。感謝您指點我正確的方向。 – Scott

+0

@斯科特:對不起。我只是試着編譯這個東西,並修正了錯誤。我現在發佈的版本應該可以工作,儘管我沒有對其進行詳盡的測試。 –

+1

關心:可能使用的HTML實體比'&「<>'要多得多! – bobince

0

如果您從網站獲取數據,您將有一個NS(Mutable)Data -Object作爲您的接收緩衝區。您只需將NSData轉換爲NSString即可:
NSString *myString = [[NSString alloc] initWithData:myRecvData usingEncoding:NSUnicodeStringEncoding]
如果您的服務器使用Unicode進行發送。如果您的服務器正在發送utf-8或其他文件,那麼您還必須在接收代碼中調整stringencoding。

here a list of all supported string-encoding-types

編輯: 看看這個so-thread

+0

不正確。 OP具有HTML實體編碼的數據,而不是實際的「unicode」數據。 –

+0

yap,但之間有一個編輯...我將更新我的答案 – thomas

+0

使用NSXMLParser解碼實體有點矯枉過正。 –

2

在HTML(和XML)的&#(number);結構被稱爲作爲字符引用,它不是Unicode特有的,除了HTML中的所有字符都是用Unicode定義的,不論是逐字還是編碼爲char acter或實體參考。 (實體引用命名那些看起來像&eacute;&amp;,如果你正在刮的HTML頁面,你肯定要對付那些爲好。)

沒有在文字解碼標準庫函數或實體參考。有關解碼HTML文本內容的方法,請參閱this question。如果您只有字符引用和標準XML實體(如&amp;),則可利用NSXMLParser解析<element> + yourstring + </element>,但這不會處理像&eacute;這樣的HTML特定實體。

一般來說,屏幕抓取最好使用合適的HTML解析器來完成,而不是使用字符串破解。這將把所有的文本內容轉換成文本節點,並隨時轉換字符和實體引用。但是,再次,標準庫中沒有可用的HTML解析器。如果目標頁面是格式良好的獨立XHTML,則可以再次使用NSXMLParser。否則,你可能想嘗試libxml2,它提供了HTML解析器和XML。有關背景信息,請參閱this question

+0

感謝您的澄清。不知道該給我打電話什麼噸。 – Scott