我正在將一個Android應用程序移植到iOS中,並且遇到了一個小障礙。我從網頁拉取HTML編碼的數據,但一些數據以Unicode顯示以顯示外來字符......所以在俄語(Летизамной)中的字符將被解析爲,"Лет..."
將iOS HTML Unicode轉換爲NSString?
在android中,我是能夠通過調用HTML.fromHTML()來解決這個問題。 iOS中有類似的東西嗎?
我正在將一個Android應用程序移植到iOS中,並且遇到了一個小障礙。我從網頁拉取HTML編碼的數據,但一些數據以Unicode顯示以顯示外來字符......所以在俄語(Летизамной)中的字符將被解析爲,"Лет..."
將iOS HTML Unicode轉換爲NSString?
在android中,我是能夠通過調用HTML.fromHTML()來解決這個問題。 iOS中有類似的東西嗎?
編寫自己的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;
}
如果您從網站獲取數據,您將有一個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。
不正確。 OP具有HTML實體編碼的數據,而不是實際的「unicode」數據。 –
yap,但之間有一個編輯...我將更新我的答案 – thomas
使用NSXMLParser解碼實體有點矯枉過正。 –
在HTML(和XML)的&#(number);
結構被稱爲作爲字符引用,它不是Unicode特有的,除了HTML中的所有字符都是用Unicode定義的,不論是逐字還是編碼爲char acter或實體參考。 (實體引用命名那些看起來像é
或&
,如果你正在刮的HTML頁面,你肯定要對付那些爲好。)
沒有在文字解碼標準庫函數或實體參考。有關解碼HTML文本內容的方法,請參閱this question。如果您只有字符引用和標準XML實體(如&
),則可利用NSXMLParser
解析<element>
+ yourstring + </element>
,但這不會處理像é
這樣的HTML特定實體。
一般來說,屏幕抓取最好使用合適的HTML解析器來完成,而不是使用字符串破解。這將把所有的文本內容轉換成文本節點,並隨時轉換字符和實體引用。但是,再次,標準庫中沒有可用的HTML解析器。如果目標頁面是格式良好的獨立XHTML,則可以再次使用NSXMLParser
。否則,你可能想嘗試libxml2,它提供了HTML解析器和XML。有關背景信息,請參閱this question。
感謝您的澄清。不知道該給我打電話什麼噸。 – Scott
這裏有什麼問題?現在UTF-8非常普遍。您沒有提供任何關於HTML解析所使用的細節的信息,或者您真正遇到的問題。 –
啊,你更新了。我認爲你的意思是數據是用HTML實體編碼的,但事實上並不包含HTML標籤? –