【问题标题】:Converting HTML text into plain text using Objective-C使用 Objective-C 将 HTML 文本转换为纯文本
【发布时间】:2013-10-14 03:10:41
【问题描述】:

我有巨大的NSString,里面有 HTML 文本。此字符串的长度超过 3.500.000 个字符。如何将此 HTML 文本转换为 NSString,其中包含纯文本。我正在使用扫描仪,但它工作得太慢了。有什么想法吗?

【问题讨论】:

标签: html ios objective-c nsstring


【解决方案1】:

这取决于您所针对的 iOS 版本。由于 iOS7 有一个内置方法,不仅可以去除 HTML 标签,还可以将格式设置为字符串:

Xcode 9/Swift 4

if let htmlStringData = htmlString.data(using: .utf8), let attributedString = try? NSAttributedString(data: htmlStringData, options: [.documentType : NSAttributedString.DocumentType.html], documentAttributes: nil) {
    print(attributedString)
}

你甚至可以像这样创建一个扩展:

extension String {
    var htmlToAttributedString: NSAttributedString? {
        guard let data = self.data(using: .utf8) else {
            return nil
        }

        do {
            return try NSAttributedString(data: data, options: [.documentType : NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil)
        } catch {
            print("Cannot convert html string to attributed string: \(error)")
            return nil
        }
    }
}

请注意,此示例代码使用 UTF8 编码。您甚至可以创建一个函数而不是计算属性并将编码添加为参数。

斯威夫特 3

let attributedString = try NSAttributedString(data: htmlString.dataUsingEncoding(NSUTF8StringEncoding)!,
                                              options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
                                              documentAttributes: nil)

Objective-C

[[NSAttributedString alloc] initWithData:[htmlString dataUsingEncoding:NSUTF8StringEncoding] options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: [NSNumber numberWithInt:NSUTF8StringEncoding]} documentAttributes:nil error:nil];

如果您只需要删除 <> 之间的所有内容(肮脏的方式!!!),如果字符串中有这些字符可能会出现问题,请使用:

- (NSString *)stringByStrippingHTML {
   NSRange r;
   NSString *s = [[self copy] autorelease];
   while ((r = [s rangeOfString:@"<[^>]+>" options:NSRegularExpressionSearch]).location != NSNotFound)
     s = [s stringByReplacingCharactersInRange:r withString:@""];
   return s;
}

【讨论】:

  • 模拟器出现内存不足异常 =(
  • 如何将 &amp 之类的 HTML 实体替换为等价的纯文本。即 &
  • @ThEuSeFuL 检查这个答案:stackoverflow.com/questions/1105169/…
  • 对我来说是完美的答案。为你 +1。
  • 请记住,使用 NSHTMLTextDocumentType 需要在被锁定的主线程上同步运行。
【解决方案2】:

我用扫描仪解决了我的问题,但我并不是将它用于所有文本。在将所有部分连接在一起之前,我将它用于每 10.000 个文本部分。下面是我的代码

-(NSString *)convertHTML:(NSString *)html {

    NSScanner *myScanner;
    NSString *text = nil;
    myScanner = [NSScanner scannerWithString:html];

    while ([myScanner isAtEnd] == NO) {

        [myScanner scanUpToString:@"<" intoString:NULL] ;

        [myScanner scanUpToString:@">" intoString:&text] ;

        html = [html stringByReplacingOccurrencesOfString:[NSString stringWithFormat:@"%@>", text] withString:@""];
    }
    //
    html = [html stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

    return html;
}

斯威夫特 4:

var htmlToString(html:String) -> String {
        var htmlStr =html;
        let scanner:Scanner = Scanner(string: htmlStr);
        var text:NSString? = nil;
        while scanner.isAtEnd == false {
            scanner.scanUpTo("<", into: nil);
            scanner.scanUpTo(">", into: &text);
            htmlStr = htmlStr.replacingOccurrences(of: "\(text ?? "")>", with: "");
        }
        htmlStr = htmlStr.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines);
        return htmlStr;
}

【讨论】:

  • 在 while 循环中添加一个@autoreleasepool 以保留内存
  • 注意:这也将替换标签之间的任何内容,因此如果您有一个像“Some Name ”这样的电子邮件地址,它将删除 。这可能不是你想要的。它可能需要查找已知 HTML 标记的映射。
【解决方案3】:

目标 C

+ (NSString*)textToHtml:(NSString*)htmlString
{
    htmlString = [htmlString stringByReplacingOccurrencesOfString:@"&quot;" withString:@"\""];
    htmlString = [htmlString stringByReplacingOccurrencesOfString:@"&apos;" withString:@"'"];
    htmlString = [htmlString stringByReplacingOccurrencesOfString:@"&amp;" withString:@"&"];
    htmlString = [htmlString stringByReplacingOccurrencesOfString:@"&lt;" withString:@"<"];
    htmlString = [htmlString stringByReplacingOccurrencesOfString:@"&gt;" withString:@">"];
    return htmlString;
}

希望这会有所帮助!

【讨论】:

  • 为什么不是 htmlToText ?
【解决方案4】:

对于 Swift 语言,

NSAttributedString(data:(htmlString as! String).dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true
            )!, options:[NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: NSNumber(unsignedLong: NSUTF8StringEncoding)], documentAttributes: nil, error: nil)!

【讨论】:

    【解决方案5】:
    - (NSString *)stringByStrippingHTML:(NSString *)inputString
    {
        NSMutableString *outString;
    
        if (inputString)
        {
            outString = [[NSMutableString alloc] initWithString:inputString];
    
            if ([inputString length] > 0)
            {
                NSRange r;
    
                while ((r = [outString rangeOfString:@"<[^>]+>|&nbsp;" options:NSRegularExpressionSearch]).location != NSNotFound)
                {
                    [outString deleteCharactersInRange:r];
                }      
            }
        }
    
        return outString; 
    }
    

    【讨论】:

      【解决方案6】:

      斯威夫特 4:

      do {
         let cleanString = try NSAttributedString(data: htmlContent.data(using: String.Encoding.utf8)!,
                                                                            options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
                                                                            documentAttributes: nil)
      } catch {
          print("Something went wrong")
      }
      

      【讨论】:

        【解决方案7】:

        通过传递编码类型作为参数可以更通用,但作为这个类别的例子:

        @implementation NSString (CSExtension)
        
            - (NSString *)htmlToText {
                return [NSAttributedString.alloc
                        initWithData:[self dataUsingEncoding:NSUnicodeStringEncoding]
                             options:@{NSDocumentTypeDocumentOption: NSHTMLTextDocumentType}
                  documentAttributes:nil error:nil].string;
            }
        
        @end
        

        【讨论】:

        • 在这个方法中你传递字符串的地方可能是自我...?
        • @Raviteja_DevObal 啊抱歉这是类别,我可以更清楚,将编辑...
        • 但是我不相信这个答案是正确的,因为他们需要大的 html 并且这非常慢。我最终使用 DTCoreText 进行了一些额外的修改以正确显示图像我的解决方案在 github 上是公开的。
        • 此方法不是从服务转换动态 HTML 文本。意味着我不知道哪些 HTML 内容来自服务。但是用自定义方法替换
        • 抱歉打错了:但我不相信这个答案不再正确,因为需要大的 html,而且速度非常慢。我最终使用 DTCoreText 进行了一些额外的修改以正确显示图像我的解决方案在 github 上是公开的。
        猜你喜欢
        • 2011-01-25
        • 2022-01-25
        • 2012-04-12
        • 2014-09-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-21
        相关资源
        最近更新 更多