it-swarm.com.de

Entfernen Sie HTML-Tags von einem NSString auf dem iPhone

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 [ >>>>>>>>>>>> ]]>
104
lfalin

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. 

307
m.kocikowski

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.

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

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

8
Mohamed AHDIDOU

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;
 }
7
Kirtikumar A.

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.

7
Colin Barrett

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:

  • Der reguläre Ausdruck wird nur einmal initialisiert.
  • Es wird eine einzelne Kopie der Originalzeichenfolge verwendet.

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.

6
hpique

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:@""];
}
5
Rémy

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

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; 
}
3
Dan J

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;
}
2
tmr

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. 

2
Ben Gottlieb

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
2
digipeople

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("&nbsp;", withString: " ")
  copy = copy.stringByReplacingOccurrencesOfString("&amp;", withString: "&")
  return copy
}
1
JohnVanDijk

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.

0
jarnoan

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

0
Nik Kov

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.

0
Ashoor

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;
}
0
jcpennypincher

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;

}

0
Ahmed Awad