目标C HTML转义/ unescape
想知道是否有一个简单的方法在Objective C中做一个简单的HTML转义/ unescape。我想要的是这样的伪代码:
NSString *string = @"<span>Foo</span>"; [string stringByUnescapingHTML];
哪个返回
<span>Foo</span>
希望能够避免所有其他的HTML实体,甚至像Ӓ之类的ASCII码。
Cocoa Touch / UIKit中有没有方法可以做到这一点?
此链接包含下面的解决scheme。 Cocoa CF具有CFXMLCreateStringByUnescapingEntitiesfunction,但在iPhone上不可用。
@interface MREntitiesConverter : NSObject <NSXMLParserDelegate>{ NSMutableString* resultString; } @property (nonatomic, retain) NSMutableString* resultString; - (NSString*)convertEntitiesInString:(NSString*)s; @end @implementation MREntitiesConverter @synthesize resultString; - (id)init { if([super init]) { resultString = [[NSMutableString alloc] init]; } return self; } - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)s { [self.resultString appendString:s]; } - (NSString*)convertEntitiesInString:(NSString*)s { if (!s) { NSLog(@"ERROR : Parameter string is nil"); } NSString* xmlStr = [NSString stringWithFormat:@"<d>%@</d>", s]; NSData *data = [xmlStr dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]; NSXMLParser* xmlParse = [[[NSXMLParser alloc] initWithData:data] autorelease]; [xmlParse setDelegate:self]; [xmlParse parse]; return [NSString stringWithFormat:@"%@",resultString]; } - (void)dealloc { [resultString release]; [super dealloc]; } @end
查看XMLEntities的NSString类别 。 有解码XML实体(包括所有HTML字符引用),编码XML实体,剥离标签和从string中删除换行符和空格的方法:
- (NSString *)stringByStrippingTags; - (NSString *)stringByDecodingXMLEntities; // Including all HTML character references - (NSString *)stringByEncodingXMLEntities; - (NSString *)stringWithNewLinesAsBRs; - (NSString *)stringByRemovingNewLinesAndWhitespace;
来自Google Toolbox for Mac的另一个HTML NSString类别
尽pipe名字,这也适用于iOS。
http://google-toolbox-for-mac.googlecode.com/svn/trunk/Foundation/GTMNSString+HTML.h
/// Get a string where internal characters that are escaped for HTML are unescaped // /// For example, '&' becomes '&' /// Handles   and 2 cases as well /// // Returns: // Autoreleased NSString // - (NSString *)gtm_stringByUnescapingFromHTML;
而且我只能在项目中包含三个文件:头文件,实现文件和GTMDefines.h
。
这是一个令人难以置信的黑客一起解决scheme,但是如果你想简单地转义一个string,而不必担心分析,这样做:
-(NSString *)htmlEntityDecode:(NSString *)string { string = [string stringByReplacingOccurrencesOfString:@""" withString:@"\""]; string = [string stringByReplacingOccurrencesOfString:@"'" withString:@"'"]; string = [string stringByReplacingOccurrencesOfString:@"<" withString:@"<"]; string = [string stringByReplacingOccurrencesOfString:@">" withString:@">"]; string = [string stringByReplacingOccurrencesOfString:@"&" withString:@"&"]; // Do this last so that, eg @"&lt;" goes to @"<" not @"<" return string; }
我知道这绝不是优雅的,但它完成了工作。 然后你可以通过调用来解码一个元素:
string = [self htmlEntityDecode:string];
就像我说的那样,它很黑,但是很有效。 如果你想编码一个string,只需反转stringByReplacingOccurencesOfString参数。
在iOS 7中,您可以使用NSAttributedString的能力导入HTML来将HTML实体转换为NSString。
例如:
@interface NSAttributedString (HTML) + (instancetype)attributedStringWithHTMLString:(NSString *)htmlString; @end @implementation NSAttributedString (HTML) + (instancetype)attributedStringWithHTMLString:(NSString *)htmlString { NSDictionary *options = @{ NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute :@(NSUTF8StringEncoding) }; NSData *data = [htmlString dataUsingEncoding:NSUTF8StringEncoding]; return [[NSAttributedString alloc] initWithData:data options:options documentAttributes:nil error:nil]; } @end
然后在你的代码中当你想清理实体时:
NSString *cleanString = [[NSAttributedString attributedStringWithHTMLString:question.title] string];
这可能是最简单的方法,但我不知道它是如何performance的。 你可能应该非常确定你的“清理”内容不包含任何<img>
标签或类似的东西,因为这个方法将在HTML到NSAttributedString转换过程中下载这些图像。 🙂
这是一个解决scheme,通过使所有的字符(通过使所有的HTML编码的实体为他们的Unicode值)…用于我的需要(确保一个string来自用户,但放置在一个Web视图不能有任何XSS攻击):
接口:
@interface NSString (escape) - (NSString*)stringByEncodingHTMLEntities; @end
执行:
@implementation NSString (escape) - (NSString*)stringByEncodingHTMLEntities { // Rather then mapping each individual entity and checking if it needs to be replaced, we simply replace every character with the hex entity NSMutableString *resultString = [NSMutableString string]; for(int pos = 0; pos<[self length]; pos++) [resultString appendFormat:@"&#x%x;",[self characterAtIndex:pos]]; return [NSString stringWithString:resultString]; } @end
用法示例:
UIWebView *webView = [[UIWebView alloc] init]; NSString *userInput = @"<script>alert('This is an XSS ATTACK!');</script>"; NSString *safeInput = [userInput stringByEncodingHTMLEntities]; [webView loadHTMLString:safeInput baseURL:nil];
你的里程会有所不同。
编码和解码HTML或XMLstring的侵入性最小,最轻量级的方法是使用GTMNSStringHTMLAdditions CocoaPod 。
这简直就是Google Toolbox for Mac NSString类别GTMNSString+HTML
,剥夺了对GTMDefines.h
的依赖。 所以你只需要添加一个.h和一个。你就可以走了。
例:
#import "GTMNSString+HTML.h" // Encoding a string with XML / HTML elements NSString *stringToEncode = @"<TheBeat>Goes On</TheBeat>"; NSString *encodedString = [stringToEncode gtm_stringByEscapingForHTML]; // encodedString looks like this now: // <TheBeat>Goes On</TheBeat> // Decoding a string with XML / HTML encoded elements NSString *stringToDecode = @"<TheBeat>Goes On</TheBeat>"; NSString *decodedString = [stringToDecode gtm_stringByUnescapingFromHTML]; // decodedString looks like this now: // <TheBeat>Goes On</TheBeat>
这是一个易于使用的NSString类别实现:
- http://code.google.com/p/qrcode-scanner-live/source/browse/trunk/iphone/Classes/NSString%2BHTML.h
- http://code.google.com/p/qrcode-scanner-live/source/browse/trunk/iphone/Classes/NSString%2BHTML.m
这是远远没有完成,但你可以从这里添加一些缺less的实体: http : //code.google.com/p/statz/source/browse/trunk/NSString%2BHTML.m
用法:
#import "NSString+HTML.h" NSString *raw = [NSString stringWithFormat:@"<div></div>"]; NSString *escaped = [raw htmlEscapedString];
上面的MREntitiesConverter是一个HTML剥离器,而不是编码器。
如果您需要编码器,请转到此处: 为XML / HTML编码NSString
MREntitiesConverter不能用于转义格式错误的XML。 它将在一个简单的URL上失败:
http://www.google.com/search?client=safari&rls=en&q=fail&ie=UTF-8&oe=UTF-8
如果你需要生成一个文字你可能会考虑使用这样的工具:
http://www.freeformatter.com/java-dotnet-escape.html#ad-output
为你完成工作。
另请参阅此答案 。
这个最简单的解决scheme是创build一个类别如下:
这里是类别的头文件:
#import <Foundation/Foundation.h> @interface NSString (URLEncoding) -(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding; @end
这是实现:
#import "NSString+URLEncoding.h" @implementation NSString (URLEncoding) -(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding { return (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)self, NULL, (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ", CFStringConvertNSStringEncodingToEncoding(encoding)); } @end
现在我们可以简单地做到这一点:
NSString *raw = @"hell & brimstone + earthly/delight"; NSString *url = [NSString stringWithFormat:@"http://example.com/example?param=%@", [raw urlEncodeUsingEncoding:NSUTF8Encoding]]; NSLog(url);
这个答案的信贷进入下面的网站: –
http://madebymany.com/blog/url-encoding-an-nsstring-on-ios
为什么不只是使用?
NSData *data = [s dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]; NSString *result = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]; return result;
Noob的问题,但在我的情况下,它的作品…
这是几年前我发布的一个旧的答案。 我的目的不是要提供一个“好”和“可敬”的解决scheme,而是一个在某些情况下可能有用的“黑客”解决scheme。 请不要使用这个解决scheme,除非没有其他的工作。
实际上,在许多情况下,其他答案并不是因为UIWebView正在完成所有工作,所以它工作得很好。 你甚至可以注入一些JavaScript(这可能是危险的和/或有用的)。 表演应该是可怕的,但实际上并不坏。
还有另外一个解决scheme需要提及。 只要创build一个UIWebView
,加载编码的string,并返回文本。 它转义标签“<>”,也解码所有的HTML实体(例如“&GT;”),它可能工作在别人不这样做(例如使用西里尔)。 我不认为这是最好的解决scheme,但如果上述解决scheme不起作用,这可能是有用的。
这是一个使用ARC的小例子:
@interface YourClass() <UIWebViewDelegate> @property UIWebView *webView; @end @implementation YourClass - (void)someMethodWhereYouGetTheHtmlString:(NSString *)htmlString { self.webView = [[UIWebView alloc] init]; NSString *htmlString = [NSString stringWithFormat:@"<html><body>%@</body></html>", self.description]; [self.webView loadHTMLString:htmlString baseURL:nil]; self.webView.delegate = self; } - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { self.webView = nil; } - (void)webViewDidFinishLoad:(UIWebView *)webView { self.webView = nil; NSString *escapedString = [self.webView stringByEvaluatingJavaScriptFromString:@"document.body.textContent;"]; } - (void)webViewDidStartLoad:(UIWebView *)webView { // Do Nothing } @end