Pregunta

Hay un par de maneras diferentes para eliminar HTML tags a partir de un NSString en Cocoa.

Una manera es para representar la cadena en un NSAttributedString y luego agarra el texto representado.

De otra manera es el uso de NSXMLDocument's -objectByApplyingXSLTString método para aplicar un XSLT transformación que hace.

Por desgracia, el iPhone no soporta NSAttributedString o NSXMLDocument.Hay demasiados casos de borde y con formato incorrecto HTML los documentos para que me sienta cómodo de usar regex o NSScanner.¿Alguien tiene una solución para esto?

Una sugerencia que ha sido simplemente el aspecto de la apertura y cierre de la etiqueta de caracteres, este método no funciona con la excepción de casos triviales.

Por ejemplo estos casos (desde el Perl libro de cocina en el capítulo sobre el mismo tema) rompería este método:

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

<!-- <A comment> -->

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

<![INCLUDE CDATA [ >>>>>>>>>>>> ]]>
¿Fue útil?

Solución

Un rápido y " sucio " (elimina todo entre la solución < y >), funciona 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;
}

Tengo esto declarado como una categoría de NSString.

Otros consejos

Este NSString la categoría de los usos de la NSXMLParser para eliminar con precisión cualquier HTML etiquetas de un NSString.Esta es una sola .m y .h archivo que puede ser incluido en su proyecto fácilmente.

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

Usted, a continuación, tira de html haciendo lo siguiente:

Importar el encabezado:

#import "NSString_stripHtml.h"

Y, a continuación, llamar a stripHtml:

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

Esto también funciona con formato incorrecto HTML que técnicamente no es XML.

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

funciona bien para mí

usa esto

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

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

no olvide incluir esto en su código: #import " RegexKitLite.h " aquí está el enlace para descargar esta API: http://regexkit.sourceforge.net/#Downloads

Eche un vistazo a NSXMLParser. Es un analizador de estilo SAX. Debería poder usarlo para detectar etiquetas u otros elementos no deseados en el documento XML e ignorarlos, capturando solo texto puro.

Puedes usar como abajo

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

Aquí hay una solución más eficiente que la respuesta aceptada:

- (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 categoría NSString anterior utiliza una expresión regular para encontrar todas las etiquetas coincidentes, hace una copia de la cadena original y finalmente elimina todas las etiquetas en su lugar al iterar sobre ellas en orden inverso. Es más eficiente porque:

  • La expresión regular se inicializa solo una vez.
  • Se utiliza una sola copia de la cadena original.

Esto funcionó bastante bien para mí, pero una solución con NSScanner podría ser más eficiente.

Al igual que la respuesta aceptada, esta solución no aborda todos los casos fronterizos solicitados por @lfalin. Esos requerirían un análisis mucho más costoso que el caso de uso promedio probablemente no necesita.

Sin un bucle (al menos de nuestro lado):

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

He extendido la respuesta por m.kocikowski e intenté hacerlo un poco más eficiente usando un NSMutableString. También lo he estructurado para usarlo en una clase de Utils estática (sé que una categoría es probablemente el mejor diseño), y eliminé la liberación automática para que se compile en un proyecto ARC.

Incluido aquí en caso de que alguien lo encuentre útil.

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

Si desea obtener el contenido sin las etiquetas html de la página web (documento HTML), utilice este código dentro del método UIWebViewDidfinishLoading delegado .

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

Me imagino que la forma más segura sería analizar < > s, ¿no? Recorra toda la cadena y copie todo lo que no esté encerrado en & Lt; & Gt; s en una nueva cadena.

Esta es la modernización de la respuesta m.kocikowski que elimina espacios en blanco:

@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

siguiente es la respuesta aceptada, pero en lugar de categoría, es un método auxiliar simple con una cadena que se le pasa. (gracias 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;
}

Aquí está la versión rápida:

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
}

Si está dispuesto a utilizar Three20 framework , tiene una categoría en NSString que agrega el método stringByRemovingHTMLTags. Consulte NSStringAdditions.h en el subproyecto Three20Core.

Ampliando esto más de las respuestas de m.kocikowski y Dan J con más explicaciones para los novatos

1 # Primero debe crear aim-c-categories para que el código sea utilizable en cualquier clase.

.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 # Luego simplemente importe el archivo .h de la clase de categoría que acaba de crear, por ejemplo,

#import "NSString+NAME_OF_CATEGORY.h"

3 # Llamando al método.

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

resultado es NSString del que quiero quitar las etiquetas.

He seguido la respuesta aceptada por m.kocikowski y modificada es ligeramente para hacer uso de una agrupación de liberación automática para limpiar todas las cadenas temporales creadas por stringByReplacingCharactersInRange

En el comentario para este método dice: / * Reemplazar caracteres en rango con la cadena especificada, devolviendo una nueva cadena. * /

Entonces, dependiendo de la longitud de su XML, puede estar creando una gran pila de nuevas cadenas de liberación automática que no se limpiarán hasta el final de la próxima @autoreleasepool. Si no está seguro de cuándo puede suceder eso o si una acción del usuario podría desencadenar repetidamente muchas llamadas a este método antes, puede concluir esto en un @autoreleasepool. Incluso se pueden anidar y usar dentro de bucles cuando sea posible.

La referencia de Apple en @autoreleasepool dice esto ... " Si escribe un bucle que crea muchos objetos temporales. Puede usar un bloque de grupo de liberación automática dentro del bucle para eliminar esos objetos antes de la próxima iteración. El uso de un bloque de grupo de liberación automática en el bucle ayuda a reducir la huella de memoria máxima de la aplicación. & Quot; No lo he usado en el bucle, pero al menos este método se limpia por sí solo ahora.

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

Otra forma:

Interfaz :

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

Implementación

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

Realización

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

o simple

NSString *myClearStr = [self stringByStrippingHTML:rudeStr];

Una respuesta actualizada para @ m.kocikowski que funciona en versiones recientes de iOS.

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

}

Aquí hay una publicación de blog que analiza un par de bibliotecas disponibles para eliminar HTML http://sugarmaplesoftware.com/25/strip-html-tags/ Tenga en cuenta los comentarios donde se ofrecen otras soluciones.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top