it-roy-ru.com

Удалить HTML-теги из NSString на iPhone

Есть несколько разных способов удалить HTML tags из NSString в Cocoa.

Один из способов - отобразить строку в NSAttributedString, а затем получить обработанный текст.

Другой способ - использовать метод NSXMLDocument's -objectByApplyingXSLTString, чтобы применить преобразование XSLT, которое это делает.

К сожалению, iPhone не поддерживает NSAttributedString или NSXMLDocument. Слишком много случаев Edge и искаженных документов HTML, чтобы я чувствовал себя комфортно, используя regex или NSScanner. У кого-нибудь есть решение этого?

Одним из предложений было просто искать открывающие и закрывающие символы тега, этот метод не будет работать, за исключением очень тривиальных случаев. 

Например, эти случаи (из главы Perl Cookbook на ту же тему) могут нарушить этот метод:

<IMG SRC = "foo.gif" ALT = "A > B">

<!-- <A comment> -->

<script>if (a<b && a>c)</script>

<![INCLUDE CDATA [ >>>>>>>>>>>> ]]>
104
lfalin

Быстрое и «грязное» (удаляет все между <и>) решение, работает с iOS> = 3.2: 

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

Я объявил это как категорию NSString. 

307
m.kocikowski

Эта категория NSString использует NSXMLParser для точного удаления любых тегов HTML из NSString. Это один файл .m и .h, который можно легко включить в ваш проект.

https://Gist.github.com/leighmcculloch/1202238

Затем вы удаляете html, выполнив следующее:

Импортируйте заголовок:

#import "NSString_stripHtml.h"

А затем вызовите stripHtml:

NSString* mystring = @"<b>Hello</b> World!!";
NSString* stripped = [mystring stripHtml];
// stripped will be = Hello World!!

Это также работает с искаженным HTML, который технически не является XML.

29
Leigh McCulloch
UITextView *textview= [[UITextView alloc]initWithFrame:CGRectMake(10, 130, 250, 170)];
NSString *str = @"This is <font color='red'>simple</font>";
[textview setValue:str forKey:@"contentToHTMLString"];
textview.textAlignment = NSTextAlignmentLeft;
textview.editable = NO;
textview.font = [UIFont fontWithName:@"vardana" size:20.0];
[UIView addSubview:textview];

работать хорошо для меня

10
MANCHIKANTI KRISHNAKISHORE

использовать этот 

NSString *myregex = @"<[^>]*>"; //regex to remove any html tag

NSString *htmlString = @"<html>bla bla</html>";
NSString *stringWithoutHTML = [hstmString stringByReplacingOccurrencesOfRegex:myregex withString:@""];

не забудьте включить это в свой код: #import "RegexKitLite.h" Вот ссылка для загрузки этого API: http://regexkit.sourceforge.net/#Downloads

8
Mohamed AHDIDOU

Вы можете использовать как ниже

-(void)myMethod
 {

 NSString* htmlStr = @"<some>html</string>";
 NSString* strWithoutFormatting = [self stringByStrippingHTML:htmlStr];

 }

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

Посмотрите на NSXMLParser. Это синтаксический анализатор в стиле SAX. Вы должны иметь возможность использовать его для обнаружения тегов или других нежелательных элементов в документе XML и игнорировать их, захватывая только чистый текст.

7
Colin Barrett

Вот более эффективное решение, чем принятый ответ:

- (NSString*)hp_stringByRemovingTags
{
    static NSRegularExpression *regex = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        regex = [NSRegularExpression regularExpressionWithPattern:@"<[^>]+>" options:kNilOptions error:nil];
    });

    // Use reverse enumerator to delete characters without affecting indexes
    NSArray *matches =[regex matchesInString:self options:kNilOptions range:NSMakeRange(0, self.length)];
    NSEnumerator *enumerator = matches.reverseObjectEnumerator;

    NSTextCheckingResult *match = nil;
    NSMutableString *modifiedString = self.mutableCopy;
    while ((match = [enumerator nextObject]))
    {
        [modifiedString deleteCharactersInRange:match.range];
    }
    return modifiedString;
}

Приведенная выше категория NSString использует регулярное выражение для поиска всех совпадающих тегов, создает копию исходной строки и, наконец, удаляет все теги на месте, перебирая их в обратном порядке. Это более эффективно, потому что:

  • Регулярное выражение инициализируется только один раз.
  • Единственная копия оригинальной строки используется.

Для меня это достаточно хорошо, но решение с использованием NSScanner может быть более эффективным.

Как и принятый ответ, это решение не охватывает все пограничные случаи, запрошенные @lfalin. Это потребует гораздо более дорогого анализа, который, скорее всего, не нужен среднему сценарию использования.

6
hpique

Без петли (по крайней мере, на нашей стороне):

- (NSString *)removeHTML {

    static NSRegularExpression *regexp;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        regexp = [NSRegularExpression regularExpressionWithPattern:@"<[^>]+>" options:kNilOptions error:nil];
    });

    return [regexp stringByReplacingMatchesInString:self
                                            options:kNilOptions
                                              range:NSMakeRange(0, self.length)
                                       withTemplate:@""];
}
5
Rémy

Если вы хотите получить содержимое без тегов html с веб-страницы (HTML-документ), используйте этот код внутри метода UIWebViewDidfinishLoading Delegate .

  NSString *myText = [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.textContent"];
4
Biranchi
#import "RegexKitLite.h"

string text = [html stringByReplacingOccurrencesOfRegex:@"<[^>]+>" withString:@""]
4
Jim Liu
NSAttributedString *str=[[NSAttributedString alloc] initWithData:[trimmedString dataUsingEncoding:NSUTF8StringEncoding] options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: [NSNumber numberWithInt:NSUTF8StringEncoding]} documentAttributes:nil error:nil];
4
Pavan Sisode

Я расширил ответ m.kocikowski и попытался сделать его немного более эффективным, используя NSMutableString. Я также структурировал его для использования в статическом классе Utils (хотя я знаю, что Категория, вероятно, является лучшим дизайном), и удалил авто-релиз, чтобы он компилировался в проекте ARC.

Включено здесь на случай, если кто-нибудь найдет это полезным.

.h

+ (NSString *)stringByStrippingHTML:(NSString *)inputString;

.m

+ (NSString *)stringByStrippingHTML:(NSString *)inputString 
{
  NSMutableString *outString;

  if (inputString)
  {
    outString = [[NSMutableString alloc] initWithString:inputString];

    if ([inputString length] > 0)
    {
      NSRange r;

      while ((r = [outString rangeOfString:@"<[^>]+>" options:NSRegularExpressionSearch]).location != NSNotFound)
      {
        [outString deleteCharactersInRange:r];
      }      
    }
  }

  return outString; 
}
3
Dan J

ниже приводится принятый ответ, но вместо категории это простой вспомогательный метод с переданной строкой. (спасибо м.кочиковски)

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

Я бы предположил, что самый безопасный способ - это разбор <> s, нет? Переберите всю строку и скопируйте все, что не заключено в <>, в новую строку. 

2
Ben Gottlieb

Это модернизация m.kocikowski ответа, которая удаляет пробелы:

@implementation NSString (StripXMLTags)

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

@end
2
digipeople

Вот версия Swift:

func stripHTMLFromString(string: String) -> String {
  var copy = string
  while let range = copy.rangeOfString("<[^>]+>", options: .RegularExpressionSearch) {
    copy = copy.stringByReplacingCharactersInRange(range, withString: "")
  }
  copy = copy.stringByReplacingOccurrencesOfString("&nbsp;", withString: " ")
  copy = copy.stringByReplacingOccurrencesOfString("&amp;", withString: "&")
  return copy
}
1
JohnVanDijk

Если вы хотите использовать Three20 framework , у него есть категория на NSString, которая добавляет метод stringByRemovingHTMLTags. Смотрите NSStringAdditions.h в подпроекте Three20Core.

0
jarnoan

Еще один способ:

Интерфейс:

-(NSString *) stringByStrippingHTML:(NSString*)inputString;

Реализация

(NSString *) stringByStrippingHTML:(NSString*)inputString
{ 
NSAttributedString *attrString = [[NSAttributedString alloc] initWithData:[inputString dataUsingEncoding:NSUTF8StringEncoding] options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)} documentAttributes:nil error:nil];
NSString *str= [attrString string]; 

//you can add here replacements as your needs:
    [str stringByReplacingOccurrencesOfString:@"[" withString:@""];
    [str stringByReplacingOccurrencesOfString:@"]" withString:@""];
    [str stringByReplacingOccurrencesOfString:@"\n" withString:@""];

    return str;
}

Реализация

cell.exampleClass.text = [self stringByStrippingHTML:[exampleJSONParsingArray valueForKey: @"key"]];

или просто

NSString *myClearStr = [self stringByStrippingHTML:rudeStr];

0
Nik Kov

Расширяя это больше от ответов m.kocikowski и Dan J с большим количеством объяснений для новичков

1 # Сначала вы должны создать target-c-Categories , чтобы сделать код пригодным для использования в любом классе.

.h

@interface NSString (NAME_OF_CATEGORY)

- (NSString *)stringByStrippingHTML;

@end

.m

@implementation NSString (NAME_OF_CATEGORY)

- (NSString *)stringByStrippingHTML
{
NSMutableString *outString;
NSString *inputString = self;

if (inputString)
{
    outString = [[NSMutableString alloc] initWithString:inputString];

    if ([inputString length] > 0)
    {
        NSRange r;

        while ((r = [outString rangeOfString:@"<[^>]+>" options:NSRegularExpressionSearch]).location != NSNotFound)
        {
            [outString deleteCharactersInRange:r];
        }
    }
}

return outString;
}

@end

2 # Затем просто импортируйте файл .h класса категории, который вы только что создали, например,.

#import "NSString+NAME_OF_CATEGORY.h"

3 # Вызов метода.

NSString* sub = [result stringByStrippingHTML];
NSLog(@"%@", sub);

результат - это NSString, с которой я хочу убрать теги.

0
Ashoor

Я следую принятому ответу m.kocikowski и немного изменил его, чтобы использовать автозапуск для очистки всех временных строк, созданных stringByReplacingCharactersInRange

В комментарии к этому методу говорится:/* Заменить символы в диапазоне указанной строкой, возвращая новую строку . * /

Таким образом, в зависимости от длины вашего XML вы можете создавать огромную кучу новых строк автоматического выпуска, которые не очищаются до конца следующего @autoreleasepool. Если вы не уверены, когда это может произойти, или если пользовательское действие могло неоднократно вызывать много вызовов этого метода раньше, тогда вы можете просто обернуть это в @autoreleasepool. Они могут даже быть вложенными и использоваться внутри циклов, где это возможно.

Ссылка Apple на @autoreleasepool гласит: «Если вы пишете цикл, который создает много временных объектов. Вы можете использовать блок пула автоматического освобождения внутри цикла, чтобы избавиться от этих объектов перед следующей итерацией. Использование блока пула автоматического выпуска в цикле помогает уменьшить максимальный объем памяти приложения ». Я не использовал его в цикле, но, по крайней мере, теперь этот метод убирает за собой.

- (NSString *) stringByStrippingHTML {
    NSString *retVal;
    @autoreleasepool {
        NSRange r;
        NSString *s = [[self copy] autorelease];
        while ((r = [s rangeOfString:@"<[^>]+>" options:NSRegularExpressionSearch]).location != NSNotFound) {
            s = [s stringByReplacingCharactersInRange:r withString:@""];
        }
        retVal = [s copy];
    } 
    // pool is drained, release s and all temp 
    // strings created by stringByReplacingCharactersInRange
    return retVal;
}
0
jcpennypincher

Обновленный ответ для @ m.kocikowski, который работает на последних версиях iOS.

-(NSString *) stringByStrippingHTMLFromString:(NSString *)str {
NSRange range;
while ((range = [str rangeOfString:@"<[^>]+>" options:NSRegularExpressionSearch]).location != NSNotFound)
    str = [str stringByReplacingCharactersInRange:range withString:@""];
return str;

}

0
Ahmed Awad