IPhone पर एक NSString से HTML टैग निकालें


106

वहाँ दूर करने के लिए अलग अलग तरीके के एक जोड़े हैं HTML tagsएक से NSStringमें Cocoa

एक तरीका स्ट्रिंग को एक में प्रस्तुत करना है NSAttributedStringऔर फिर प्रदान किए गए पाठ को पकड़ना है।

एक और तरीका उपयोग करने के लिए है NSXMLDocument's- objectByApplyingXSLTStringएक XSLTपरिवर्तन लागू करने की विधि जो इसे करती है।

दुर्भाग्य से, iPhone समर्थन नहीं करता है NSAttributedStringया NSXMLDocumentHTMLरेगेक्स या का उपयोग करके आरामदायक महसूस करने के लिए मेरे लिए बहुत सारे किनारे मामले और विकृत दस्तावेज हैं NSScanner। क्या किसी के पास इसका कोई समाधान है?

एक सुझाव केवल टैग पात्रों को खोलने और बंद करने के लिए देखा गया है, यह विधि बहुत तुच्छ मामलों को छोड़कर काम नहीं करेगी।

उदाहरण के लिए ये मामले (उसी विषय पर पर्ल कुकबुक अध्याय से) इस विधि को तोड़ देंगे:

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

<!-- <A comment> -->

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

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

आप उद्धरण और एपोस्ट्रोफ़ को ध्यान में रखने के लिए थोड़ा तर्क जोड़ सकते हैं ... सीडीएटीए थोड़ा अधिक काम करेगा, लेकिन HTML का संपूर्ण बिंदु यह है कि अज्ञात टैग को पार्सर द्वारा अनदेखा किया जा सकता है; यदि आप सभी टैग को अज्ञात मानते हैं, तो आपको बस कच्चा पाठ प्राप्त करना चाहिए।
बेन गोटलिब

मैं टिप्पणी करना चाहता हूं कि एक अच्छी (लेकिन बुनियादी) नियमित अभिव्यक्ति निश्चित रूप से आपके उदाहरणों पर नहीं टूटेगी। निश्चित रूप से नहीं अगर आप अच्छी तरह से गठित एक्सएचटीएमएल की गारंटी दे सकते हैं। मुझे पता है कि आपने कहा था कि आप नहीं कर सकते, लेकिन मुझे आश्चर्य है कि ;-)
जेक

1
इस सवाल का अच्छा जवाब हैHTML को उद्देश्यपूर्ण c
vipintj

दुर्भाग्य से, NSScanner का उपयोग बहुत धीमा है।
स्टेपीटेट

इससे भी अधिक दुर्भाग्य से, जुड़ा हुआ NSScanner उदाहरण केवल तुच्छ HTML के लिए काम करता है। यह मेरी पोस्ट में उल्लिखित प्रत्येक परीक्षण मामले के लिए विफल रहता है।
लैफलिन

जवाबों:


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

मैंने इसे एक श्रेणी ओएस एनएसएसट्रिंग के रूप में घोषित किया है।


4
@ जेम्स समाधान में तैनात विधि का उपयोग करने के लिए। आपको NSString के लिए एक श्रेणी बनानी होगी। Google में "उद्देश्य-सी श्रेणी" देखें। तब आप उस विधि को m फ़ाइल में जोड़ते हैं, और h फ़ाइल में प्रोटोटाइप। जब वह सब सेट हो जाता है, तो इसका उपयोग करने के लिए आपको एक स्ट्रिंग ऑब्जेक्ट रखना होगा (उदाहरण: NSString * myString = ...) और आप अपनी स्ट्रिंग ऑब्जेक्ट पर उस विधि को कॉल करते हैं (NSString * स्ट्रिप्डस्ट्रिंग = [myrring stringByStrippingHTML]; )।
रॉबर्टो

3
नियमित अभिव्यक्तियों के लिए +1 महान उपयोग, लेकिन दुर्भाग्य से बहुत सारे मामलों को कवर नहीं करता है।
मटका

3
वास्तव में त्वरित और गंदा .... इस फ़ंक्शन के कारण मेरे एप्लिकेशन में बहुत बड़ी मेमोरी लीक हो गई है ... खैर, इसके बचाव में, मैं बड़ी मात्रा में डेटा का उपयोग कर रहा हूं ....
EZFrag

5
मेरे ऐप में इस समाधान के कारण प्रदर्शन समस्याएं पैदा हुईं। मैंने NSScanner के बजाय NSRegularExpressionSearch के साथ एक समाधान पर स्विच किया। अब प्रदर्शन की समस्याएं खत्म हो गई हैं
carmen_munich

2
यह बहुत बहुत स्मृति और समय लेने वाली है। केवल html की छोटी मात्रा के साथ इसका उपयोग करें!
१०:११ बजे ullstrm

29

यह NSStringश्रेणी NSXMLParserकिसी भी HTMLटैग को सही से हटाने के लिए उपयोग करती है NSString। यह एक एकल .mऔर .hफ़ाइल है जिसे आसानी से आपकी परियोजना में शामिल किया जा सकता है।

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

फिर आप htmlनिम्न कार्य करके पट्टी करें :

हेडर आयात करें:

#import "NSString_stripHtml.h"

और उसके बाद स्ट्रिपटीलेट को कॉल करें:

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

यह विकृत रूप से काम करता है HTMLजो तकनीकी रूप से नहीं है XML


3
जबकि नियमित अभिव्यक्ति (जैसा कि m.kocikowski द्वारा कहा गया है) त्वरित और गंदा है, यह अधिक मजबूत है। उदाहरण स्ट्रिंग: @ "मेरा परीक्षण <स्पान फ़ॉन्ट = \" फ़ॉन्ट> नाम \ "> html स्ट्रिंग"। यह उत्तर देता है: मेरा परीक्षण html स्ट्रिंग। नियमित अभिव्यक्ति रिटर्न: मेरा परीक्षण नाम "> html स्ट्रिंग। जब तक यह आम नहीं है, यह सिर्फ और अधिक मजबूत है।
डोनाले

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

संभवतः सबसे अच्छा समाधान है, लेकिन यह एक 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" यहाँ इस एपीआई को डाउनलोड करने के लिए लिंक है: http://regexkit.sourceforge.net/#Downloads


7

NSXMLParser पर एक नज़र डालें। यह एक एसएएक्स शैली का पार्सर है। आपको एक्सएमएल दस्तावेज़ में टैग या अन्य अवांछित तत्वों का पता लगाने और उन्हें अनदेखा करने के लिए इसका उपयोग करने में सक्षम होना चाहिए, केवल शुद्ध पाठ पर कब्जा करना।


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

यह स्वीकृत उत्तर होना चाहिए। वर्तमान एक हास्यास्पद व्यर्थ है।
अडलई हॉलर

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

जब हमारे पास HTML टैग्स के साथ मेटा डेटा है और उस टैग को लागू करना चाहते हैं, तो उस समय हमें इच्छा उत्पादन प्राप्त करने के लिए उपरोक्त कोड को लागू करना चाहिए।
पवन सिन्धु

4
#import "RegexKitLite.h"

string text = [html stringByReplacingOccurrencesOfRegex:@"<[^>]+>" withString:@""]

2
HTML एक नियमित भाषा नहीं है, इसलिए आपको इसे नियमित अभिव्यक्ति के साथ पार्स / स्ट्रिप करने की कोशिश नहीं करनी चाहिए। stackoverflow.com/questions/1732348/…
csaunders

3

मैंने m.kocikowski द्वारा उत्तर दिया है और NSMutableString का उपयोग करके इसे थोड़ा अधिक कुशल बनाने की कोशिश की है। मैंने इसे एक स्टैटिक यूटिल्स क्लास में उपयोग के लिए संरचित किया है (मुझे पता है कि एक श्रेणी शायद सबसे अच्छा डिज़ाइन है), और ऑटोरेलिज़ को हटा दिया, ताकि यह एआरसी प्रोजेक्ट में संकलित हो।

यदि कोई इसे उपयोगी पाता है तो यहाँ शामिल है।

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

@ फिर बस regex को <(?>/?)(?!a).+?>इसमें बदलें, खुलने वाले सभी टैग को हटा देगा <a> और समापन </a> टैग।
आशूर

3

यदि आप वेब पेज (HTML डॉक्यूमेंट) से HTML टैग के बिना सामग्री प्राप्त करना चाहते हैं, तो इस कोड का उपयोग UIWebViewDidfinishLoading प्रतिनिधि विधि के अंदर करें ।

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

<br> को कुछ भी नहीं बदला जा रहा है ... जो अवांछनीय है।
निशांत

2

मुझे लगता है कि सबसे सुरक्षित तरीका सिर्फ पार्स करने के लिए होगा, नहीं? पूरे स्ट्रिंग के माध्यम से लूप करें, और एक नए स्ट्रिंग में <> s में संलग्न कुछ भी कॉपी न करें।


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
}

stringByReplacingOccurrencesOfStringचक्र के बाहर यू , यू का उपयोग प्रतिशत एन्कोडिंग है और इसे सही तरीके से तय किया जाना चाहिए।
व्याचेस्लाव गेरिकोव 12

0

यदि आप तीन20 ढांचे का उपयोग करने के इच्छुक हैं , तो इसमें NSString पर एक श्रेणी है जो stringByRemovingHTMLTags विधि को जोड़ता है। NSStringAdditions.h को तीन20Core उपप्रोजेक्ट में देखें।


26
भगवान के लिए, किसी भी चीज़ के लिए तीन20 का उपयोग न करें। सबसे फूला हुआ और खराब टिप्पणी वाला ढांचा।
कोमपोज़र

0

M.kocikowski's और Dan J के उत्तरों को अधिक विस्तार के साथ newbies के लिए अधिक विस्तार से

1 # सबसे पहले आपको किसी भी वर्ग में कोड को प्रयोग करने योग्य बनाने के लिए ऑब्जेक्टिव-सी-कैटेगरी बनानी होगी ।

@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 द्वारा स्वीकृत उत्तर का पालन करना है और संशोधित किया गया है जो कि सभी स्ट्रिंग स्ट्रिंग द्वारा बनाए गए अस्थायी तारों को साफ करने के लिए ऑटोरेलिस्पूल का उपयोग करने के लिए है।

इस पद्धति के लिए टिप्पणी में कहा गया है, / * निर्दिष्ट स्ट्रिंग के साथ सीमा में वर्ण बदलें, नई स्ट्रिंग लौटाएंगे। * /

तो, अपने XML की लंबाई के आधार पर आप नए ऑटोरेलिज़ स्ट्रिंग्स का एक बड़ा ढेर बना सकते हैं, जो अगले @autoreleasepool के अंत तक साफ नहीं किए जाते हैं। यदि आप अनिश्चित हैं कि ऐसा कब हो सकता है या यदि कोई उपयोगकर्ता क्रिया बार-बार इस विधि से कई कॉल को ट्रिगर कर सकती है, तो आप इसे केवल @autoreleasepool में लपेट सकते हैं। इनसे घोंसला भी बनाया जा सकता है और जहां संभव हो वहां लूप के भीतर उपयोग किया जा सकता है।

@Autoreleasepool पर Apple के संदर्भ में यह कहा गया है ... "यदि आप एक लूप लिखते हैं जो कई अस्थायी ऑब्जेक्ट्स बनाता है। आप अगली पुनरावृत्ति से पहले उन ऑब्जेक्ट्स को डिस्पोज़ करने के लिए लूप के अंदर एक ऑटोरेलिज़ पूल ब्लॉक का उपयोग कर सकते हैं। लूप में एक ऑटोरेलेज़ पूल ब्लॉक का उपयोग करना। एप्लिकेशन के अधिकतम मेमोरी फ़ुटप्रिंट को कम करने में मदद करता है। ” मैंने इसे लूप में इस्तेमाल नहीं किया है, लेकिन कम से कम यह विधि अब खुद के बाद साफ हो जाती है।

- (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 को पार्स करना चाहता हूं
Krutarth Patel

मेरा समय बचा लिया। समाधान
Krutarth पटेल

0

@ M.kocikowski के लिए एक अद्यतन उत्तर जो हाल के iOS संस्करणों पर काम करता है।

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

}


-3

यहाँ एक ब्लॉग पोस्ट को लिए अलग एचटीएमएल उपलब्ध पुस्तकालयों की एक जोड़ी की चर्चा है http://sugarmaplesoftware.com/25/strip-html-tags/ नोट टिप्पणियाँ जहाँ दूसरों समाधान की पेशकश कर रहे हैं।


यह टिप्पणियों का सटीक सेट है जो मैंने अपने प्रश्न में एक उदाहरण के रूप में जुड़ा हुआ है जो काम नहीं करेगा।
3
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.