Es gibt verschiedene Möglichkeiten, HTML tags
von einer NSString
in Cocoa
zu entfernen.
Eine Möglichkeit ist, den String in eine NSAttributedString
zu rendern und dann den gerenderten Text zu packen.
Eine andere Möglichkeit ist die Verwendung der NSXMLDocument's
-objectByApplyingXSLTString
-Methode, um eine XSLT
-Transformation anzuwenden, die dies ausführt.
Leider unterstützt das iPhone NSAttributedString
oder NSXMLDocument
nicht. Es gibt zu viele Edge-Fälle und fehlerhafte HTML
-Dokumente, damit ich mich mit Regex oder NSScanner
wohlfühle. Hat jemand eine Lösung dafür?
Ein Vorschlag war, einfach nach öffnenden und schließenden Tag-Zeichen zu suchen. Diese Methode funktioniert nur in sehr trivialen Fällen.
Zum Beispiel würden diese Fälle (aus dem Perl-Kochbuch-Kapitel zum gleichen Thema) diese Methode zerstören:
<IMG SRC = "foo.gif" ALT = "A > B">
<!-- <A comment> -->
<script>if (a<b && a>c)</script>
<![INCLUDE CDATA [ >>>>>>>>>>>> ]]>
Eine schnelle und "schmutzige" Lösung (entfernt alles zwischen <und>), funktioniert mit 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;
}
Ich habe dies als eine Kategorie von NSString deklariert.
Diese NSString
-Kategorie verwendet die NSXMLParser
, um HTML
-Tags aus einer NSString
genau zu entfernen. Dies ist eine einzelne .m
- und .h
-Datei, die problemlos in Ihr Projekt eingefügt werden kann.
https://Gist.github.com/leighmcculloch/1202238
Sie entfernen dann html
, indem Sie folgendermaßen vorgehen:
Importieren Sie den Header:
#import "NSString_stripHtml.h"
Dann rufen Sie stripHtml auf:
NSString* mystring = @"<b>Hello</b> World!!";
NSString* stripped = [mystring stripHtml];
// stripped will be = Hello World!!
Dies funktioniert auch bei missgebildeten HTML
, die technisch XML
nicht sind.
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];
arbeit gut für mich
benutze das
NSString *myregex = @"<[^>]*>"; //regex to remove any html tag
NSString *htmlString = @"<html>bla bla</html>";
NSString *stringWithoutHTML = [hstmString stringByReplacingOccurrencesOfRegex:myregex withString:@""];
vergiss nicht, dies in deinen Code aufzunehmen: #import "RegexKitLite.h" Hier ist der Link zum Herunterladen dieser API: http://regexkit.sourceforge.net/#Downloads
Sie können wie unten verwenden
-(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;
}
Schauen Sie sich NSXMLParser an. Es ist ein Parser im SAX-Stil. Sie sollten in der Lage sein, Tags oder andere unerwünschte Elemente im XML-Dokument zu erkennen, diese zu ignorieren und nur reinen Text aufzunehmen.
Hier ist eine effizientere Lösung als die akzeptierte Antwort:
- (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;
}
Die obige NSString
-Kategorie verwendet einen regulären Ausdruck, um alle übereinstimmenden Tags zu finden, kopiert die ursprüngliche Zeichenfolge und entfernt schließlich alle vorhandenen Tags, indem sie in umgekehrter Reihenfolge durchlaufen werden. Es ist effizienter, weil:
Dies ist für mich gut genug, aber eine Lösung mit NSScanner
ist möglicherweise effizienter.
Wie die akzeptierte Antwort behandelt diese Lösung nicht alle von @lfalin geforderten Grenzfälle. Dies würde ein viel teureres Parsing erfordern, das der durchschnittliche Anwendungsfall höchstwahrscheinlich nicht benötigt.
Ohne Schleife (zumindest auf unserer Seite):
- (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:@""];
}
Wenn Sie den Inhalt ohne die HTML-Tags von der Webseite (HTML-Dokument) abrufen möchten, verwenden Sie diesen Code in der UIWebViewDidfinishLoading
delegate -Methode.
NSString *myText = [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.textContent"];
#import "RegexKitLite.h"
string text = [html stringByReplacingOccurrencesOfRegex:@"<[^>]+>" withString:@""]
NSAttributedString *str=[[NSAttributedString alloc] initWithData:[trimmedString dataUsingEncoding:NSUTF8StringEncoding] options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: [NSNumber numberWithInt:NSUTF8StringEncoding]} documentAttributes:nil error:nil];
Ich habe die Antwort von m.kocikowski erweitert und versucht, sie mit NSMutableString etwas effizienter zu gestalten. Ich habe es auch für die Verwendung in einer statischen Utils-Klasse strukturiert (ich weiß, dass eine Kategorie wahrscheinlich das beste Design ist) und die Autorelease entfernt, sodass sie in einem ARC-Projekt kompiliert werden kann.
Hier eingeschlossen, falls jemand es für nützlich hält.
.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;
}
folgendes ist die akzeptierte Antwort, aber anstelle von category ist es eine einfache Hilfsmethode, in die string übergeben wird. (danke m.kocikowski)
-(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;
}
Ich würde mir vorstellen, der sicherste Weg wäre, nur für <> s zu analysieren, nein? Durchlaufen Sie die gesamte Zeichenfolge und kopieren Sie alles, was nicht in <> s eingeschlossen ist, in eine neue Zeichenfolge.
Dies ist die Modernisierung von m.kocikowski answer.
@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
Hier ist die Swift-Version:
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
}
Wenn Sie Three20 Framework verwenden möchten, hat es eine Kategorie für NSString, die die Methode stringByRemovingHTMLTags hinzufügt. Siehe NSStringAdditions.h im Three20Core-Unterprojekt.
Ein anderer Weg:
Schnittstelle:
-(NSString *) stringByStrippingHTML:(NSString*)inputString;
Implementierung
(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;
}
Realisierung
cell.exampleClass.text = [self stringByStrippingHTML:[exampleJSONParsingArray valueForKey: @"key"]];
oder einfach
NSString *myClearStr = [self stringByStrippingHTML:rudeStr];
Dies aus den Antworten von m.kocikowski und Dan J mit weiteren Erklärungen für Neulinge
1 # Zuerst müssen Sie Objective-C-Kategorien erstellen, um den Code für jede Klasse nutzbar zu machen.
.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 # Importieren Sie einfach die Datei .h der gerade erstellten Kategorieklasse, z.
#import "NSString+NAME_OF_CATEGORY.h"
3 # Die Methode aufrufen.
NSString* sub = [result stringByStrippingHTML];
NSLog(@"%@", sub);
Ergebnis ist NSString, von dem ich die Tags entfernen möchte.
Ich habe der akzeptierten Antwort von m.kocikowski gefolgt und modifiziert, ist ein wenig, um einen Autoreleasepool zu verwenden, um alle temporären Zeichenfolgen zu bereinigen, die von stringByReplacingCharactersInRange erstellt werden
In dem Kommentar für diese Methode heißt es:/* Ersetzen Sie Zeichen im Bereich durch die angegebene Zeichenfolge, und geben Sie die neue Zeichenfolge zurück.
Abhängig von der Länge Ihres XML-Dokuments können Sie also einen riesigen Stapel neuer Autorelease-Zeichenfolgen erstellen, die erst am Ende des nächsten @autoreleasepools bereinigt werden. Wenn Sie sich nicht sicher sind, wann dies passieren kann oder wenn eine Benutzeraktion zuvor mehrfach Aufrufe dieser Methode auslösen konnte, können Sie dies einfach in einem @autoreleasepool zusammenfassen. Diese können sogar geschachtelt und wenn möglich innerhalb von Schleifen verwendet werden.
Apples Referenz auf @autoreleasepool besagt Folgendes: "Wenn Sie eine Schleife schreiben, die viele temporäre Objekte erstellt. Sie können einen Block für die Blockfreilaufung innerhalb der Schleife verwenden, um diese Objekte vor der nächsten Iteration zu entsorgen hilft, den maximalen Speicherbedarf der Anwendung zu reduzieren. " Ich habe es nicht in der Schleife benutzt, aber zumindest räumt diese Methode jetzt nach.
- (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;
}
Eine aktualisierte Antwort für @ m.kocikowski, die mit den letzten iOS-Versionen funktioniert.
-(NSString *) stringByStrippingHTMLFromString:(NSString *)str {
NSRange range;
while ((range = [str rangeOfString:@"<[^>]+>" options:NSRegularExpressionSearch]).location != NSNotFound)
str = [str stringByReplacingCharactersInRange:range withString:@""];
return str;
}