74

想知道是否有一种简单的方法可以在 Objective C 中执行简单的 HTML 转义/取消转义。我想要的是类似这样的伪代码:

NSString *string = @"<span>Foo</span>";
[string stringByUnescapingHTML];

哪个返回

<span>Foo</span>

希望也能取消转义所有其他 HTML 实体,甚至 Ӓ 之类的 ASCII 代码。

Cocoa Touch/UIKit 中是否有任何方法可以做到这一点?

4

14 回答 14

91

查看我的NSString 类别的 XMLEntities。有一些方法可以解码 XML 实体(包括所有 HTML 字符引用)、编码 XML 实体、剥离标签以及从字符串中删除换行符和空格:

- (NSString *)stringByStrippingTags;
- (NSString *)stringByDecodingXMLEntities; // Including all HTML character references
- (NSString *)stringByEncodingXMLEntities;
- (NSString *)stringWithNewLinesAsBRs;
- (NSString *)stringByRemovingNewLinesAndWhitespace;
于 2010-05-16T11:02:03.357 回答
35

来自Google Toolbox for Mac的另一个 HTML NSString 类别
尽管名称如此,但它也适用于 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, '&amp;' becomes '&'
///  Handles &#32; and &#x32; cases as well
///
//  Returns:
//    Autoreleased NSString
//
- (NSString *)gtm_stringByUnescapingFromHTML;

而且我只需要在项目中包含三个文件:header、implementation 和GTMDefines.h.

于 2011-03-02T05:48:47.897 回答
30

链接包含以下解决方案。Cocoa CF 具有 CFXMLCreateStringByUnescapingEntities 函数,但在 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
于 2009-03-18T18:51:47.630 回答
29

这是我所做的一个令人难以置信的组合解决方案,但是如果您想简单地转义字符串而不担心解析,请执行以下操作:

-(NSString *)htmlEntityDecode:(NSString *)string
    {
        string = [string stringByReplacingOccurrencesOfString:@"&quot;" withString:@"\""];
        string = [string stringByReplacingOccurrencesOfString:@"&apos;" withString:@"'"];
        string = [string stringByReplacingOccurrencesOfString:@"&lt;" withString:@"<"];
        string = [string stringByReplacingOccurrencesOfString:@"&gt;" withString:@">"];
        string = [string stringByReplacingOccurrencesOfString:@"&amp;" withString:@"&"]; // Do this last so that, e.g. @"&amp;lt;" goes to @"&lt;" not @"<"

        return string;
    }

我知道这绝不是优雅的,但它可以完成工作。然后,您可以通过调用来解码元素:

string = [self htmlEntityDecode:string];

就像我说的,它很hacky,但它有效。如果要对字符串进行编码,只需反转 stringByReplacingOccurencesOfString 参数即可。

于 2010-09-16T15:50:05.660 回答
11

在 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];

这可能是最简单的方法,但我不知道它的性能如何。您可能应该非常确定您的“清理”内容不包含任何<img>标签或类似的东西,因为此方法将在 HTML 到 NSAttributedString 转换期间下载这些图像。:)

于 2014-02-20T07:30:50.290 回答
5

这是一个中和所有字符的解决方案(通过使它们成为其 unicode 值的所有 HTML 编码实体)......根据我的需要使用它(确保来自用户但放置在 webview 内部的字符串不能有任何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];

您的里程会有所不同。

于 2013-01-05T02:04:46.467 回答
4

编码和解码 HTML 或 XML 字符串的侵入性最小且最轻量级的方法是使用GTMNSStringHTMLAdditions CocoaPod

它只是 Google Toolbox for Mac NSString 类别GTMNSString+HTML,去掉了对GTMDefines.h. 因此,您只需添加一个 .h 和一个 .m,就可以开始了。

例子:

#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:
// &lt;TheBeat&gt;Goes On&lt;/TheBeat&gt;

// Decoding a string with XML / HTML encoded elements
NSString *stringToDecode = @"&lt;TheBeat&gt;Goes On&lt;/TheBeat&gt;";
NSString *decodedString = [stringToDecode gtm_stringByUnescapingFromHTML];

// decodedString looks like this now:
// <TheBeat>Goes On</TheBeat>
于 2015-09-09T16:44:04.153 回答
2

这是一个易于使用的 NSString 类别实现:

它远未完成,但您可以从此处添加一些缺失的实体: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];
于 2010-05-31T18:00:28.330 回答
1

上面的 MREntitiesConverter 是一个 HTML 剥离器,而不是编码器。

如果你需要一个编码器,去这里:Encode NSString for XML/HTML

于 2009-12-19T05:12:52.737 回答
0

MREntitiesConverter 不适用于转义格式错误的 xml。它会在一个简单的 URL 上失败:

http://www.google.com/search?client=safari&rls=en&q=fail&ie=UTF-8&oe=UTF-8

于 2009-09-21T01:50:05.820 回答
0

如果您需要生成文字,您可以考虑使用这样的工具:

http://www.freeformatter.com/java-dotnet-escape.html#ad-output

为您完成工作。

另请参阅此答案

于 2014-02-26T19:09:00.667 回答
0

这个最简单的解决方案是创建一个类别,如下所示:

这是该类别的头文件:

#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
于 2015-02-11T16:28:08.363 回答
-4

为什么不直接使用?

NSData *data = [s dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
NSString *result = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
return result;

菜鸟问题,但就我而言,它有效......

于 2011-02-18T10:21:55.797 回答
-5

这是我几年前发布的旧答案。我的目的不是提供一个“好的”和“受人尊敬的”解决方案,而是一个在某些情况下可能有用的“hacky”解决方案。请不要使用此解决方案,除非没有其他方法。

实际上,它在许多情况下都可以正常工作,因为 UIWebView 正在完成所有工作。你甚至可以注入一些 javascript(这可能是危险的和/或有用的)。表现应该很糟糕,但实际上并没有那么糟糕。

还有一个必须提到的解决方案。只需创建一个UIWebView,加载编码的字符串并取回文本。它转义标签“<>”,还解码所有 html 实体(例如“>”),它可能在其他人不这样做的地方工作(例如使用西里尔字母)。我认为这不是最好的解决方案,但如果上述解决方案不起作用,它会很有用。

下面是一个使用 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
于 2013-09-08T19:13:56.250 回答