Удалить HTML-теги из NSString на iPhone
Существует несколько способов удалить HTML tags
из NSString
в Cocoa
.
Один из способов - отобразить строку в NSAttributedString
, а затем захватить визуализированный текст.
Другим способом является использование метода NSXMLDocument's
- objectByApplyingXSLTString
для применения преобразования XSLT
, которое это делает.
К сожалению, iPhone не поддерживает NSAttributedString
или NSXMLDocument
. Слишком много краевых случаев и неправильных документов HTML
для меня, чтобы чувствовать себя комфортно с помощью регулярного выражения или NSScanner
. У кого-нибудь есть решение?
Одно из предложений заключалось в том, чтобы просто искать открывающие и закрывающие теги символов, этот метод не будет работать, за исключением очень тривиальных случаев.
Например, эти случаи (из главы Perl Cookbook по тому же вопросу) нарушили бы этот метод:
<IMG SRC = "foo.gif" ALT = "A > B">
<!-- <A comment> -->
<script>if (a<b && a>c)</script>
<![INCLUDE CDATA [ >>>>>>>>>>>> ]]>
Ответы
Ответ 1
Быстрое и "грязное" (удаляет все между < и > ) решением, работает с 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;
}
У меня это объявлено как категория os NSString.
Ответ 2
В этой категории 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
.
Ответ 3
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];
отлично работает для меня
Ответ 4
используйте этот
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
Ответ 5
Взгляните на NSXMLParser. Это синтаксический анализатор SAX. Вы должны иметь возможность использовать его для обнаружения тегов или других нежелательных элементов в документе XML и игнорировать их, захватывая только чистый текст.
Ответ 6
Вы можете использовать, как показано ниже
-(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
Здесь более эффективное решение, чем принятый ответ:
- (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. Для этого потребуется гораздо более дорогостоящий синтаксический анализ, который, скорее всего, не понадобится среднему варианту использования.
Ответ 8
Без цикла (по крайней мере, на нашей стороне):
- (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:@""];
}
Ответ 9
#import "RegexKitLite.h"
string text = [html stringByReplacingOccurrencesOfRegex:@"<[^>]+>" withString:@""]
Ответ 10
NSAttributedString *str=[[NSAttributedString alloc] initWithData:[trimmedString dataUsingEncoding:NSUTF8StringEncoding] options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: [NSNumber numberWithInt:NSUTF8StringEncoding]} documentAttributes:nil error:nil];
Ответ 11
Если вы хотите получить контент без тэгов html с веб-страницы (HTML-документ), используйте этот код внутри метода UIWebViewDidfinishLoading
делегировать.
NSString *myText = [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.textContent"];
Ответ 12
Я продлил ответ m.kocikowski и попытался сделать его более эффективным, используя NSMutableString. Я также структурировал его для использования в статическом классе Utils (я знаю, что Категория, вероятно, лучший дизайн) и удалил авторекламу, поэтому она компилируется в проекте ARC.
Включается здесь, если кто-либо сочтет это полезным.
.h
+ (NSString *)stringByStrippingHTML:(NSString *)inputString;
ого
+ (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;
}
Ответ 13
Я бы предположил, что самый безопасный способ - просто разобрать на < > s, no? Прокрутите всю строку и скопируйте все, что не заключено в < > s, в новую строку.
Ответ 14
Это модернизация ответа 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
Ответ 15
Ниже приведен принятый ответ, но вместо категории это простой вспомогательный метод со строкой, переданной в него. (спасибо м.коциковски)
-(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;
}
Ответ 16
Это сообщение было действительно полезно, если вы уже проанализировали XML и не хотите снова разбирать содержимое.
Обновление
Старая ссылка больше не работает. Обновлено сообщение здесь
Ответ 17
Здесь быстрая версия:
func stripHTMLFromString(string: String) -> String {
var copy = string
while let range = copy.rangeOfString("<[^>]+>", options: .RegularExpressionSearch) {
copy = copy.stringByReplacingCharactersInRange(range, withString: "")
}
copy = copy.stringByReplacingOccurrencesOfString(" ", withString: " ")
copy = copy.stringByReplacingOccurrencesOfString("&", withString: "&")
return copy
}
Ответ 18
Если вы хотите использовать структуру 320, у нее есть категория в NSString, которая добавляет метод stringByRemovingHTMLTags. См. NSStringAdditions.h в подпроекте Three20Core.
Ответ 19
Расширение этого больше от m.kocikowski и Dan J дает больше объяснений для новичков
1 # Сначала вам нужно создать objective-c-categories, чтобы сделать код пригодным для использования в любом классе.
.h
@interface NSString (NAME_OF_CATEGORY)
- (NSString *)stringByStrippingHTML;
@end
ого
@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. Я хочу удалить теги из.
Ответ 20
Я следую принятому ответу m.kocikowski и модифицировал немного, чтобы использовать autoreleasepool для очистки всех временных строк, которые создаются с помощью 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;
}
Ответ 21
Другой способ:
Интерфейс:
-(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];
Ответ 22
Обновленный ответ для @m.kocikowski, который работает в последних версиях iOS.
-(NSString *) stringByStrippingHTMLFromString:(NSString *)str {
NSRange range;
while ((range = [str rangeOfString:@"<[^>]+>" options:NSRegularExpressionSearch]).location != NSNotFound)
str = [str stringByReplacingCharactersInRange:range withString:@""];
return str;
}
Ответ 23
Вот сообщение в блоге, в котором обсуждается несколько библиотек, доступных для удаления HTML
http://sugarmaplesoftware.com/25/strip-html-tags/
Обратите внимание на комментарии, в которых предлагаются другие решения.