web-dev-qa-db-ja.com

iPhoneのNSStringからHTMLタグを削除する

NSString内のCocoaからHTML tagsを削除する方法はいくつかあります。

1つの方法 は、文字列をNSAttributedStringにレンダリングしてから、レンダリングされたテキストを取得します。

別の方法 は、NSXMLDocument's -objectByApplyingXSLTStringメソッドを使用して、それを行うXSLT変換を適用することです。

残念ながら、iPhoneはNSAttributedStringまたはNSXMLDocumentをサポートしていません。正規表現またはHTMLを使用して快適に感じるには、エッジケースと不正なNSScannerドキュメントが多すぎます。誰にもこれに対する解決策がありますか?

1つの提案は、単に開始および終了タグ文字を探すことです。この方法は、非常に些細な場合を除いて機能しません。

たとえば、これらのケース(同じテーマに関するPerlクックブックの章から)は、この方法を破ります:

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

<!-- <A comment> -->

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

<![INCLUDE CDATA [ >>>>>>>>>>>> ]]>
104
lfalin

迅速で「ダーティ」なソリューション(<と>の間のすべてを削除)ソリューションは、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;
}

これをNSStringカテゴリとして宣言しました。

307
m.kocikowski

この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でも機能します。

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

私のためにうまくいく

これを使って

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

8
Mohamed AHDIDOU

以下のように使用できます

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

NSXMLParserを見てください。これは、SAXスタイルのパーサーです。これを使用して、XMLドキュメント内のタグまたはその他の不要な要素を検出し、それらを無視して、純粋なテキストのみをキャプチャできるようにする必要があります。

7
Colin Barrett

受け入れられている答えよりも効率的なソリューションを次に示します。

- (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によって要求されたすべての境界ケースに対応しているわけではありません。これらは、平均的なユースケースではほとんど必要のない、はるかに高価な解析を必要とします。

6
hpique

ループなし(少なくとも私たちの側では):

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

私はm.kocikowskiによる回答を拡張し、NSMutableStringを使用して、それをもう少し効率的にしようとしました。また、静的なUtilsクラスで使用するために構造化しており(カテゴリがおそらく最適なデザインであることがわかっています)、自動リリースを削除して、ARCプロジェクトでコンパイルします。

誰かがそれを役に立つと思う場合に備えて、ここに含まれます。

。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

Webページ(HTMLドキュメント)からhtmlタグなしでコンテンツを取得する場合は、UIWebViewDidfinishLoadingdelegateメソッド内でこのコードを使用します。

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

以下は受け入れられた答えですが、カテゴリの代わりに、文字列が渡された単純なヘルパーメソッドです。 (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

最も安全な方法は、<>を解析することだけだと思いますか?文字列全体をループし、<>で囲まれていないものを新しい文字列にコピーします。

2
Ben Gottlieb

これは、空白を削除する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

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

Three20 framework を使用する場合、NSStringにstringByRemovingHTMLTagsメソッドを追加するカテゴリがあります。 Three20CoreサブプロジェクトのNSStringAdditions.hを参照してください。

0
jarnoan

別の方法:

インターフェース:

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

0
Nik Kov

これをm.kocikowskiとDan Jの回答からさらに拡張し、初心者向けの説明を追加

1#最初に objective-c-categories を作成して、任意のクラスでコードを使用可能にする必要があります。

。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#次に、作成したばかりのカテゴリクラスの。hファイルをインポートします。

#import "NSString+NAME_OF_CATEGORY.h"

3#メソッドの呼び出し。

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

resultはタグを削除したいNSStringです。

0
Ashoor

私はm.kocikowskiによる受け入れられた答えに従っており、stringByReplacingCharactersInRangeによって作成されたすべての一時的な文字列をクリーンアップするためにautoreleasepoolをわずかに使用するように修正されています

このメソッドのコメントには、/ *範囲内の文字を指定された文字列で置き換え、新しい文字列を返します。 * /

したがって、XMLの長さによっては、次の@autoreleasepoolの終わりまでクリーンアップされない新しい自動リリース文字列の巨大な山を作成している可能性があります。それがいつ起こるかわからない場合、またはユーザーアクションがこのメソッドへの多くの呼び出しを繰り返しトリガーする可能性がある場合は、@ autoreleasepoolでこれをラップできます。これらはネストされ、可能であればループ内で使用することもできます。

Appleの@autoreleasepoolに関するリファレンスには、「...多くの一時オブジェクトを作成するループを作成する場合、ループ内で自動解放プールブロックを使用して、次の反復の前にそれらのオブジェクトを破棄できます。アプリケーションの最大メモリフットプリントの削減に役立ちます。」ループでは使用していませんが、少なくともこのメソッドは今ではクリーンアップされています。

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

最新のiOSバージョンで動作する@ m.kocikowskiの更新された回答。

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

}

0
Ahmed Awad