iPhoneのNSStringからHTMLタグを削除する
-
07-07-2019 - |
質問
HTML tags
のNSString
からCocoa
を削除する方法はいくつかあります。
1つの方法は、文字列をNSAttributedString
にレンダリングしてからレンダリングされたテキストを取得します。
別の方法は、NSXMLDocument's
-<= >それを行うobjectByApplyingXSLTString
変換を適用するメソッド。
残念ながら、iPhoneはXSLT
またはNSXMLDocument
をサポートしていません。正規表現またはHTML
を使用して快適に感じるには、エッジケースと不正なNSScanner
ドキュメントが多すぎます。誰にもこれに対する解決策がありますか?
提案の1つは、単に開始タグと終了タグの文字を探すことです。この方法は、非常に些細な場合を除いて機能しません。
たとえば、これらのケース(同じテーマに関するPerlクックブックの章から)は、この方法を破ります:
<IMG SRC = "foo.gif" ALT = "A > B">
<!-- <A comment> -->
<script>if (a<b && a>c)</script>
<![INCLUDE CDATA [ >>>>>>>>>>>> ]]>
解決
迅速かつ<!> quot; dirty <!> quot; (<!> lt;と<!> gt;の間のすべてを削除)ソリューション、iOSで動作<!> gt; = 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
から.m
タグを正確に削除します。これは、プロジェクトに簡単に含めることができる単一の.h
およびhtml
ファイルです。
https://gist.github.com/leighmcculloch/1202238
次に、以下を実行してXML
を削除します。
ヘッダーのインポート:
#import "NSString_stripHtml.h"
そしてstripHtmlを呼び出します:
NSString* mystring = @"<b>Hello</b> World!!";
NSString* stripped = [mystring stripHtml];
// stripped will be = Hello World!!
これは、技術的に<=>ではない不正な<=>でも機能します。
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 <!> quot; RegexKitLite.h <!> quot; このAPIをダウンロードするためのリンクは次のとおりです。 http://regexkit.sourceforge.net/#Downloads
NSXMLParserを見てください。これは、SAXスタイルのパーサーです。 XMLドキュメント内のタグまたはその他の不要な要素を検出し、それらを無視して、純粋なテキストのみをキャプチャするために使用できるはずです。
以下のように使用できます
-(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;
}
承認された回答よりも効率的なソリューションを次に示します。
- (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
デリゲートメソッド内でこのコードを使用します。
NSString *myText = [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.textContent"];
<!> lt; <!> gt; sを解析することが最も安全な方法だと思いますか?文字列全体をループし、<!> lt; <!> gt; sで囲まれていないものを新しい文字列にコピーします。
これは、空白を削除する 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
フォローは受け入れられた答えですが、カテゴリの代わりに、文字列が渡された単純なヘルパーメソッドです。 (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;
}
ここに迅速なバージョンがあります:
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フレームワークを使用する場合、NSStringにstringByRemovingHTMLTagsメソッドを追加するカテゴリがあります。 Three20CoreサブプロジェクトのNSStringAdditions.hを参照してください。
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で、タグを削除したい。
このメソッドのコメントには、/ *範囲内の文字を指定された文字列で置き換え、新しい文字列を返します。 * /
したがって、XMLの長さによっては、次の@autoreleasepoolの終わりまでクリーンアップされない新しい自動リリース文字列の巨大な山を作成する場合があります。いつ発生するかわからない場合、またはユーザーアクションによってこのメソッドの呼び出しが何度もトリガーされる可能性がある場合は、@ autoreleasepoolでこれをラップできます。可能であれば、これらをネストしてループ内で使用することもできます。
@autoreleasepoolのAppleのリファレンスでは、このように述べられています... <!> quot;多数の一時オブジェクトを作成するループを記述する場合。ループ内で自動解放プールブロックを使用して、次の反復の前にこれらのオブジェクトを破棄できます。ループで自動解放プールブロックを使用すると、アプリケーションの最大メモリフットプリントを削減できます。<!> quot;ループでは使用していませんが、少なくともこのメソッドはそれ自体をクリーンアップします。
- (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;
}
もう1つの方法:
インターフェース:
-(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];
最新のiOSバージョンで動作する@ m.kocikowskiの更新された回答。
-(NSString *) stringByStrippingHTMLFromString:(NSString *)str {
NSRange range;
while ((range = [str rangeOfString:@"<[^>]+>" options:NSRegularExpressionSearch]).location != NSNotFound)
str = [str stringByReplacingCharactersInRange:range withString:@""];
return str;
}
ここでは、HTMLのストリッピングに使用できるいくつかのライブラリについて説明しているブログ投稿があります http://sugarmaplesoftware.com/25/strip-html-tags/ 他のソリューションが提供されているコメントに注意してください。