Domanda

Esistono un paio di modi diversi per rimuovere HTML tags da un NSString in Cocoa.

Un modo è rendere la stringa in un NSAttributedString e quindi prendi il testo renderizzato.

Un altro modo è usare NSXMLDocument's - <= > metodo per applicare una objectByApplyingXSLTString trasformazione che lo fa.

Sfortunatamente, l'iPhone non supporta XSLT o NSXMLDocument. Ci sono troppi casi limite e documenti HTML non validi per farmi sentire a mio agio con regex o NSScanner. Qualcuno ha una soluzione a questo?

Un suggerimento è stato quello di cercare semplicemente l'apertura e la chiusura di caratteri tag, questo metodo non funzionerà se non per casi molto banali.

Ad esempio questi casi (dal capitolo Perl Cookbook sullo stesso argomento) rompono questo metodo:

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

<!-- <A comment> -->

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

<![INCLUDE CDATA [ >>>>>>>>>>>> ]]>
È stato utile?

Soluzione

Un veloce e " dirty " (rimuove tutto tra < e >) soluzione, funziona con 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;
}

L'ho dichiarato come categoria os NSString.

Altri suggerimenti

Questa NSString categoria utilizza NSXMLParser per rimuovere con precisione tutti i HTML tag da un .m. Questo è un singolo .h e html file che può essere facilmente incluso nel tuo progetto.

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

Quindi rimuovere XML procedendo come segue:

Importa l'intestazione:

#import "NSString_stripHtml.h"

E poi chiama stripHtml:

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

Funziona anche con <=> non valido che tecnicamente non è <=>.

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

funziona bene per me

usa questo

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

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

non dimenticare di includerlo nel tuo codice: #import " RegexKitLite.h " ecco il link per scaricare questa API: http://regexkit.sourceforge.net/#Downloads

Dai un'occhiata a NSXMLParser. È un parser in stile SAX. Dovresti essere in grado di usarlo per rilevare tag o altri elementi indesiderati nel documento XML e ignorarli, catturando solo testo puro.

Puoi usare come sotto

-(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;
 }

Ecco una soluzione più efficiente della risposta accettata:

- (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;
}

La precedente categoria NSString usa un'espressione regolare per trovare tutti i tag corrispondenti, crea una copia della stringa originale e infine rimuove tutti i tag in atto ripetendoli in ordine inverso. È più efficiente perché:

  • L'espressione regolare viene inizializzata una sola volta.
  • Viene utilizzata una singola copia della stringa originale.

Ciò ha funzionato abbastanza bene per me, ma una soluzione che utilizza NSScanner potrebbe essere più efficiente.

Come la risposta accettata, questa soluzione non risolve tutti i casi limite richiesti da @lfalin. Ciò richiederebbe un'analisi molto più costosa di cui il caso d'uso medio molto probabilmente non ha bisogno.

Senza loop (almeno dalla nostra parte):

- (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:@""];
}
#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];

Ho esteso la risposta di m.kocikowski e ho provato a renderlo un po 'più efficiente usando un NSMutableString. L'ho anche strutturato per l'uso in una classe Utils statica (so che una categoria è probabilmente il miglior design) e ho rimosso il rilascio automatico in modo che si compili in un progetto ARC.

Incluso qui nel caso in cui qualcuno lo ritenga utile.

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

Se si desidera ottenere il contenuto senza i tag html dalla pagina Web (documento HTML), utilizzare questo codice all'interno del metodo UIWebViewDidfinishLoading delegato .

  NSString *myText = [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.textContent"];

Immagino che il modo più sicuro sarebbe quello di analizzare < > s, no? Passa attraverso l'intera stringa e copia tutto ciò che non è racchiuso tra & Lt; & Gt; s in una nuova stringa.

Questa è la modernizzazione della risposta m.kocikowski che rimuove gli spazi bianchi:

@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

seguente è la risposta accettata, ma invece della categoria, è un semplice metodo di supporto con una stringa passata al suo interno. (grazie 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;
}

Ecco la versione rapida:

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
}

Se si desidera utilizzare framework Three20 , ha una categoria su NSString che aggiunge il metodo stringByRemovingHTMLTags. Vedi NSStringAdditions.h nel sottoprogetto Three20Core.

Estendendo questo più dalle risposte di m.kocikowski e Dan J con maggiori spiegazioni per i neofiti

1 # Per prima cosa devi creare goal-c-categorie per rendere il codice utilizzabile in qualsiasi classe.

.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 # Quindi importa semplicemente il file .h della classe di categoria che hai appena creato, ad esempio

#import "NSString+NAME_OF_CATEGORY.h"

3 # Richiamo del metodo.

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

risultato è NSString da cui desidero rimuovere i tag.

Ho seguito la risposta accettata da m.kocikowski e modificato è leggermente per utilizzare un autoreleasepool per ripulire tutte le stringhe temporanee create da stringByReplacingCharactersInRange

Nel commento per questo metodo indica, / * Sostituisci i caratteri nell'intervallo con la stringa specificata, restituendo una nuova stringa. * /

Quindi, a seconda della lunghezza del tuo XML, potresti creare un enorme mucchio di nuove stringhe di rilascio automatico che non vengono ripulite fino alla fine del prossimo @autoreleasepool. Se non sei sicuro di ciò che potrebbe accadere o se un'azione dell'utente potrebbe innescare ripetutamente molte chiamate a questo metodo prima di allora puoi semplicemente concludere questo in un @autoreleasepool. Se possibile, possono anche essere nidificati e utilizzati all'interno di loop.

Il riferimento di Apple su @autoreleasepool indica questo ... " Se scrivi un ciclo che crea molti oggetti temporanei. È possibile utilizzare un blocco pool di rilascio automatico all'interno del ciclo per eliminare tali oggetti prima della successiva iterazione. L'uso di un blocco pool con rilascio automatico nel loop aiuta a ridurre il footprint di memoria massima dell'applicazione. & Quot; Non l'ho usato nel ciclo, ma almeno questo metodo ripulisce dopo se stesso ora.

- (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;
}

Un altro modo:

Interfaccia:

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

Implementazione

(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;
}

Realizzazione

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

o semplice

NSString *myClearStr = [self stringByStrippingHTML:rudeStr];

Una risposta aggiornata per @ m.kocikowski che funziona su versioni recenti di iOS.

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

}

Ecco un post sul blog che discute un paio di librerie disponibili per lo stripping HTML http://sugarmaplesoftware.com/25/strip-html-tags/ Nota i commenti in cui sono offerte altre soluzioni.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top