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 [ >>>>>>>>>>>> ]]>
迅速で「ダーティ」なソリューション(<と>の間のすべてを削除)ソリューションは、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カテゴリとして宣言しました。
この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
でも機能します。
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
以下のように使用できます
-(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;
}
NSXMLParserを見てください。これは、SAXスタイルのパーサーです。これを使用して、XMLドキュメント内のタグまたはその他の不要な要素を検出し、それらを無視して、純粋なテキストのみをキャプチャできるようにする必要があります。
受け入れられている答えよりも効率的なソリューションを次に示します。
- (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によって要求されたすべての境界ケースに対応しているわけではありません。これらは、平均的なユースケースではほとんど必要のない、はるかに高価な解析を必要とします。
ループなし(少なくとも私たちの側では):
- (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];
私は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;
}
Webページ(HTMLドキュメント)からhtmlタグなしでコンテンツを取得する場合は、UIWebViewDidfinishLoading
delegateメソッド内でこのコードを使用します。
NSString *myText = [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.textContent"];
以下は受け入れられた答えですが、カテゴリの代わりに、文字列が渡された単純なヘルパーメソッドです。 (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;
}
最も安全な方法は、<>を解析することだけだと思いますか?文字列全体をループし、<>で囲まれていないものを新しい文字列にコピーします。
これは、空白を削除する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
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(" ", withString: " ")
copy = copy.stringByReplacingOccurrencesOfString("&", withString: "&")
return copy
}
Three20 framework を使用する場合、NSStringにstringByRemovingHTMLTagsメソッドを追加するカテゴリがあります。 Three20CoreサブプロジェクトのNSStringAdditions.hを参照してください。
別の方法:
インターフェース:
-(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];
これを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です。
私は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;
}
最新のiOSバージョンで動作する@ m.kocikowskiの更新された回答。
-(NSString *) stringByStrippingHTMLFromString:(NSString *)str {
NSRange range;
while ((range = [str rangeOfString:@"<[^>]+>" options:NSRegularExpressionSearch]).location != NSNotFound)
str = [str stringByReplacingCharactersInRange:range withString:@""];
return str;
}