iPhone의 NSString에서 HTML 태그 제거


106

제거하는 다른 몇 가지 방법이 있습니다 HTML tags에서 NSString에서가 Cocoa.

한 가지 방법 은 문자열을로 렌더링 NSAttributedString한 다음 렌더링 된 텍스트를 가져 오는 것입니다.

또 다른 방법NSXMLDocument's- objectByApplyingXSLTString방법 을 사용 하여 XSLT변환 을 적용하는 것입니다.

불행히도 iPhone은 NSAttributedString또는 NSXMLDocument. HTML정규식 또는 .NET을 사용하는 것이 편안하다고 느끼기 에는 너무 많은 엣지 케이스와 잘못된 문서가 NSScanner있습니다. 누구든지 이것에 대한 해결책이 있습니까?

한 가지 제안은 여는 태그 문자와 닫는 태그 문자를 찾는 것이 었습니다.이 방법은 매우 사소한 경우를 제외하고는 작동하지 않습니다.

예를 들어 이러한 경우 (동일한 주제에 대한 Perl Cookbook 장에서 발췌)는이 방법을 손상시킵니다.

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

<!-- <A comment> -->

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

<![INCLUDE CDATA [ >>>>>>>>>>>> ]]>

따옴표와 아포스트로피를 고려하기 위해 약간의 논리를 추가 할 수 있습니다. CDATA는 약간의 작업을 필요로하지만 HTML의 요점은 파서가 알 수없는 태그를 무시할 수 있다는 것입니다. 모든 태그를 알 수없는 것으로 취급하면 원시 텍스트 만 가져와야합니다.
Ben Gottlieb

좋은 (그러나 기본적인) 정규식이 귀하의 예제에서 확실히 깨지지 않을 것이라고 언급하고 싶습니다. 잘 구성된 XHTML을 보장 할 수 있다면 확실하지 않습니다. 난 당신이 할 수없는 것을 알고,하지만 난 왜이 ;-) 궁금
제이크

1
좋은 대답 이 질문에 대한이. 패턴 화 된 HTML 목표 C를 사용하여
vipintj

불행히도 NSScanner를 사용하는 것은 느립니다.
steipete 2011 년

더 불행히도 링크 된 NSScanner 예제는 간단한 html에서만 작동합니다. 내 게시물에서 언급 한 모든 테스트 사례에서 실패합니다.
lfalin 2013 년

답변:


309

빠르고 "더티"(<와> 사이의 모든 것을 제거) 솔루션은 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으로 선언했습니다.


4
@James 솔루션에 게시 된 방법을 사용합니다. NSString에 대한 카테고리를 생성해야합니다. Google에서 "Objective-C 카테고리"를 찾습니다. 그런 다음 m 파일에 해당 메서드를 추가하고 h 파일에 프로토 타입을 추가합니다. 모든 설정이 완료되면 문자열 객체 (예 : NSString * myString = ...)를 사용하고 해당 메서드를 문자열 객체 (NSString * strippedString = [myString stringByStrippingHTML])에서 호출하기 만하면됩니다. ).
Roberto

3
+1 정규 표현식에 많이 사용되지만 안타깝게도 많은 경우를 다루지는 않습니다.
matm

3
신속하고 더러운 참 ....이 기능은 .... 내 응용 프로그램에서 큰 메모리 누수가 ... 음, 그것의 방어에, 나는 많은 양의 데이터를 사용하고 원인
EZFrag

5
내 앱에서이 솔루션은 성능 문제를 일으켰습니다. NSRegularExpressionSearch 대신 NSScanner를 사용하는 솔루션으로 전환했습니다. 이제 성능 문제가 사라 졌어요
carmen_munich

2
매우 메모리와 시간이 많이 소요됩니다. 소량의 html에서만 사용하십시오!
ullstrm 2014

29

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
정규 표현식 (m.kocikowski가 말했듯이)은 빠르고 더럽지 만 더 강력합니다. 예제 문자열 : @ "My test <span font = \"font> name \ "> html string". 이 대답은 다음을 반환합니다. My test html string. 정규 표현식은 다음을 반환합니다 : My test name "> html string. 이것은 일반적이지 않지만 더 강력합니다.
DonnaLea

1
"S & P 500"과 같은 문자열이있는 경우를 제외하고는 앰퍼샌드 뒤의 모든 항목을 제거하고 문자열 "S"를 반환합니다.
조슈아 그로스

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

나를 위해 잘 작동


1
이 솔루션에 인코딩 문제가 있습니다
KIDdAe 2014 년

아마도 최상의 솔루션 일 것입니다. 그러나 UILabel에는 쓸모가 없습니다. :-(
Zeb

9

아래와 같이 사용할 수 있습니다.

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

8

이것을 사용하십시오

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


7

NSXMLParser를 살펴보십시오. SAX 스타일 파서입니다. XML 문서에서 태그 또는 기타 원치 않는 요소를 감지하고이를 무시하고 순수한 텍스트 만 캡처하는 데 사용할 수 있어야합니다.


6

다음은 허용되는 답변보다 더 효율적인 솔루션입니다.

- (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이 요청한 모든 경계 사례를 해결하지 않습니다. 평균 사용 사례에서는 필요하지 않은 훨씬 더 비싼 파싱이 필요합니다.


5

루프가 없으면 (적어도 우리 쪽) :

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

이것은 받아 들여진 대답이어야합니다. 현재는 말도 안되게 낭비입니다.
Adlai Holler

5
NSAttributedString *str=[[NSAttributedString alloc] initWithData:[trimmedString dataUsingEncoding:NSUTF8StringEncoding] options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: [NSNumber numberWithInt:NSUTF8StringEncoding]} documentAttributes:nil error:nil];

HTML 태그가있는 메타 데이터가 있고 해당 태그를 적용하고 싶을 때, 그 때 원하는 출력을 얻기 위해 위 코드를 적용해야합니다.
Pavan Sisode 2015 년


3

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

이 방법은 내가 필요하다면 나는이 방법이 충족 업데이트 할 수 있습니다 같은 링크 <A> 같은 몇 가지 태그를 비 스트립, 유용하지만
WOD

@wod 그런 다음 정규식을 변경하면 <(?>/?)(?!a).+?>여는 <a> 및 닫는 </a> 태그를 제외한 모든 태그가 제거됩니다.
Ashoor

3

웹 페이지 (HTML 문서)에서 html 태그없이 콘텐츠를 가져 오려면 UIWebViewDidfinishLoading delegate 메소드 내에서이 코드를 사용하십시오 .

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

<br>은 (는) 아무것도 대체되지 않습니다. 이는 바람직하지 않습니다.
Nishant 2013 년

2

가장 안전한 방법은 <>에 대해 구문 분석하는 것입니다. 전체 문자열을 반복하고 <>로 묶이지 않은 항목을 새 문자열에 복사합니다.


2

이것은 공백을 제거하는 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

2

다음은 허용되는 대답이지만 범주 대신 문자열이 전달 된 간단한 도우미 메서드입니다. (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

다음은 신속한 버전입니다.

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
}

Man, stringByReplacingOccurrencesOfStringu는 사이클 밖에서 사용하는 것은 백분율 인코딩이며 올바른 방법을 통해 수정되어야합니다.
Vyachaslav Gerchicov

0

Three20 프레임 워크 를 사용하려는 경우 NSString에 stringByRemovingHTMLTags 메소드를 추가하는 카테고리가 있습니다. Three20Core 하위 프로젝트의 NSStringAdditions.h를 참조하십시오.


26
제발, Three20을 아무것도 사용하지 마십시오. 지금까지 가장 부풀고 나쁜 댓글이 달린 프레임 워크.
kompozer

0

초보자를위한 더 많은 설명과 함께 m.kocikowski와 Dan J의 답변에서 이것을 더 확장하십시오.

1 # 먼저 모든 클래스에서 코드를 사용할 수 있도록 하기 위해 목표 -c- 카테고리 를 만들어야합니다.

.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입니다.


0

나는 m.kocikowski가 받아 들인 대답을 따르고 있으며 autoreleasepool을 사용하여 stringByReplacingCharactersInRange에 의해 생성 된 모든 임시 문자열을 정리하기 위해 약간 수정되었습니다.

이 메서드에 대한 주석에서 / * 범위의 문자를 지정된 문자열로 바꾸고 새 문자열을 반환합니다. * /

따라서 XML의 길이에 따라 다음 @autoreleasepool이 끝날 때까지 정리되지 않는 새로운 자동 릴리스 문자열의 거대한 더미를 만들 수 있습니다. 언제 발생하는지 확실하지 않거나 사용자 작업이 이전에이 메소드에 대한 많은 호출을 반복적으로 트리거 할 수 있는지 여부를 @autoreleasepool로 래핑 할 수 있습니다. 이들은 가능한 경우 중첩되어 루프 내에서 사용할 수도 있습니다.

@autoreleasepool에 대한 Apple의 참조는 다음과 같이 설명합니다. "여러 임시 객체를 생성하는 루프를 작성하는 경우. 루프 내부에 autorelease 풀 블록을 사용하여 다음 반복 전에 해당 객체를 처리 할 수 ​​있습니다. 루프에서 자동 릴리스 풀 블록 사용 응용 프로그램의 최대 메모리 공간을 줄이는 데 도움이됩니다. " 나는 그것을 루프에서 사용하지 않았지만 적어도이 방법은 지금 자체적으로 정리됩니다.

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

또 다른 방법 :

상호 작용:

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


HTML을 제거하고이 방법은 내가 할 구문 분석 HTML string.what 원하는 tags.but
Krutarth 파텔

내 time.nice 솔루션 저장
Krutarth 파텔

0

최신 iOS 버전에서 작동하는 @ m.kocikowski에 대한 업데이트 된 답변입니다.

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

}


-3

다음은 HTML 제거에 사용할 수있는 몇 가지 라이브러리에 대해 설명하는 블로그 게시물입니다. http://sugarmaplesoftware.com/25/strip-html-tags/ 다른 솔루션이 제공되는 주석에 유의하십시오.


이것은 작동하지 않을 것의 예로서 내 질문에서 링크 한 정확한 주석 세트입니다.
lfalin
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.