আমি কীভাবে এইচটিএমএল সত্তাকে সুইফটে ডিকোড করব?


121

আমি একটি সাইট থেকে একটি জেএসএন ফাইল টানছি এবং প্রাপ্ত স্ট্রিংগুলির মধ্যে একটি হ'ল:

The Weeknd ‘King Of The Fall’ [Video Premiere] | @TheWeeknd | #SoPhi

আমি কীভাবে জিনিসগুলিকে &#8216সঠিক চরিত্রে রূপান্তর করতে পারি ?

এটি প্রদর্শনের জন্য আমি একটি এক্সকোড খেলার মাঠ তৈরি করেছি:

import UIKit

var error: NSError?
let blogUrl: NSURL = NSURL.URLWithString("http://sophisticatedignorance.net/api/get_recent_summary/")
let jsonData = NSData(contentsOfURL: blogUrl)

let dataDictionary = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: &error) as NSDictionary

var a = dataDictionary["posts"] as NSArray

println(a[0]["title"])

উত্তর:


157

এই উত্তরটি সর্বশেষে সুইফ্ট 5.2 এবং আইওএস 13.4 এসডিকে জন্য সংশোধিত হয়েছিল।


এটি করার সহজ সরল কোনও উপায় নেই তবে আপনি NSAttributedStringএই প্রক্রিয়াটিকে যতটা সম্ভব বেদনাবিহীন করতে ম্যাজিক ব্যবহার করতে পারেন (সতর্কতা অবলম্বন করুন যে এই পদ্ধতিটি সমস্ত এইচটিএমএল ট্যাগগুলিও ছাঁটাই করবে)।

শুধুমাত্র মূল থ্রেড থেকে আরম্ভNSAttributedString করার কথা মনে রাখবেন । এটি ওয়েবকিটটি এইচটিএমএলকে নীচে পার্স করার জন্য ব্যবহার করে, যাতে প্রয়োজনীয়তা।

// This is a[0]["title"] in your case
let encodedString = "The Weeknd <em>&#8216;King Of The Fall&#8217;</em>"

guard let data = htmlEncodedString.data(using: .utf8) else {
    return
}

let options: [NSAttributedString.DocumentReadingOptionKey: Any] = [
    .documentType: NSAttributedString.DocumentType.html,
    .characterEncoding: String.Encoding.utf8.rawValue
]

guard let attributedString = try? NSAttributedString(data: data, options: options, documentAttributes: nil) else {
    return
}

// The Weeknd ‘King Of The Fall’
let decodedString = attributedString.string
extension String {

    init?(htmlEncodedString: String) {

        guard let data = htmlEncodedString.data(using: .utf8) else {
            return nil
        }

        let options: [NSAttributedString.DocumentReadingOptionKey: Any] = [
            .documentType: NSAttributedString.DocumentType.html,
            .characterEncoding: String.Encoding.utf8.rawValue
        ]

        guard let attributedString = try? NSAttributedString(data: data, options: options, documentAttributes: nil) else {
            return nil
        }

        self.init(attributedString.string)

    }

}

let encodedString = "The Weeknd <em>&#8216;King Of The Fall&#8217;</em>"
let decodedString = String(htmlEncodedString: encodedString)

54
কি? এক্সটেনশানগুলি নতুন কার্যকারিতা সরবরাহ করতে বিদ্যমান ধরণের প্রসারিত করতে বোঝানো হয়।
আকাশীবাস্কি

4
আপনি কী বলতে চাইছেন তা আমি বুঝতে পেরেছি, তবে এক্সটেনশনগুলিকে অগ্রাহ্য করা কোনও উপায় নয়।
আকাশিভস্কি 21

1
@akashivskyy: অ ASCII অক্ষর দিয়ে সঠিকভাবে এই কার্যকর করতে আপনি একটি NSCharacterEncodingDocumentAttribute, তুলনা যোগ আছে stackoverflow.com/a/27898167/1187415
মার্টিন আর

13
এই পদ্ধতিটি অত্যন্ত ভারী এবং টেবিলভিউ বা গ্রিডভিউগুলিতে প্রস্তাবিত নয়
Guido Lodetti

1
এটা অসাধারণ! যদিও এটি মূল থ্রেডকে ব্লক করে, ব্যাকগ্রাউন্ড থ্রেডে চালানোর কোনও উপায় আছে কি?
এমএমভি

78

@ আকাশীবস্কিয়ের উত্তর দুর্দান্ত এবং এটি NSAttributedStringএইচটিএমএল সত্তাগুলি ডিকোড করতে কীভাবে ব্যবহার করতে হবে তা প্রদর্শন করে । একটি সম্ভাব্য অসুবিধা (যেমন তিনি বলেছিলেন) হ'ল সমস্ত HTML মার্কআপও সরানো হয়েছে, তাই

<strong> 4 &lt; 5 &amp; 3 &gt; 2</strong>

হয়ে

4 < 5 & 3 > 2

ওএস এক্স-এ রয়েছে CFXMLCreateStringByUnescapingEntities()যা কাজটি করে:

let encoded = "<strong> 4 &lt; 5 &amp; 3 &gt; 2 .</strong> Price: 12 &#x20ac;.  &#64; "
let decoded = CFXMLCreateStringByUnescapingEntities(nil, encoded, nil) as String
println(decoded)
// <strong> 4 < 5 & 3 > 2 .</strong> Price: 12.  @ 

তবে এটি আইওএস এ উপলব্ধ নয়।

এখানে একটি খাঁটি সুইফ্ট বাস্তবায়ন। এটি &lt;অভিধান ব্যবহার করার মতো অক্ষর সত্তা রেফারেন্সগুলি এবং সমস্ত সংখ্যাযুক্ত অক্ষর সত্তা যেমন &#64বা এর মতো করে ডিকোড করে &#x20ac। (দ্রষ্টব্য যে আমি 252 টি এইচটিএমএল সত্তাকে স্পষ্টভাবে তালিকাভুক্ত করিনি))

সুইফট 4:

// Mapping from XML/HTML character entity reference to character
// From http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references
private let characterEntities : [ Substring : Character ] = [
    // XML predefined entities:
    "&quot;"    : "\"",
    "&amp;"     : "&",
    "&apos;"    : "'",
    "&lt;"      : "<",
    "&gt;"      : ">",

    // HTML character entity references:
    "&nbsp;"    : "\u{00a0}",
    // ...
    "&diams;"   : "♦",
]

extension String {

    /// Returns a new string made by replacing in the `String`
    /// all HTML character entity references with the corresponding
    /// character.
    var stringByDecodingHTMLEntities : String {

        // ===== Utility functions =====

        // Convert the number in the string to the corresponding
        // Unicode character, e.g.
        //    decodeNumeric("64", 10)   --> "@"
        //    decodeNumeric("20ac", 16) --> "€"
        func decodeNumeric(_ string : Substring, base : Int) -> Character? {
            guard let code = UInt32(string, radix: base),
                let uniScalar = UnicodeScalar(code) else { return nil }
            return Character(uniScalar)
        }

        // Decode the HTML character entity to the corresponding
        // Unicode character, return `nil` for invalid input.
        //     decode("&#64;")    --> "@"
        //     decode("&#x20ac;") --> "€"
        //     decode("&lt;")     --> "<"
        //     decode("&foo;")    --> nil
        func decode(_ entity : Substring) -> Character? {

            if entity.hasPrefix("&#x") || entity.hasPrefix("&#X") {
                return decodeNumeric(entity.dropFirst(3).dropLast(), base: 16)
            } else if entity.hasPrefix("&#") {
                return decodeNumeric(entity.dropFirst(2).dropLast(), base: 10)
            } else {
                return characterEntities[entity]
            }
        }

        // ===== Method starts here =====

        var result = ""
        var position = startIndex

        // Find the next '&' and copy the characters preceding it to `result`:
        while let ampRange = self[position...].range(of: "&") {
            result.append(contentsOf: self[position ..< ampRange.lowerBound])
            position = ampRange.lowerBound

            // Find the next ';' and copy everything from '&' to ';' into `entity`
            guard let semiRange = self[position...].range(of: ";") else {
                // No matching ';'.
                break
            }
            let entity = self[position ..< semiRange.upperBound]
            position = semiRange.upperBound

            if let decoded = decode(entity) {
                // Replace by decoded character:
                result.append(decoded)
            } else {
                // Invalid entity, copy verbatim:
                result.append(contentsOf: entity)
            }
        }
        // Copy remaining characters to `result`:
        result.append(contentsOf: self[position...])
        return result
    }
}

উদাহরণ:

let encoded = "<strong> 4 &lt; 5 &amp; 3 &gt; 2 .</strong> Price: 12 &#x20ac;.  &#64; "
let decoded = encoded.stringByDecodingHTMLEntities
print(decoded)
// <strong> 4 < 5 & 3 > 2 .</strong> Price: 12.  @

সুইফট 3:

// Mapping from XML/HTML character entity reference to character
// From http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references
private let characterEntities : [ String : Character ] = [
    // XML predefined entities:
    "&quot;"    : "\"",
    "&amp;"     : "&",
    "&apos;"    : "'",
    "&lt;"      : "<",
    "&gt;"      : ">",

    // HTML character entity references:
    "&nbsp;"    : "\u{00a0}",
    // ...
    "&diams;"   : "♦",
]

extension String {

    /// Returns a new string made by replacing in the `String`
    /// all HTML character entity references with the corresponding
    /// character.
    var stringByDecodingHTMLEntities : String {

        // ===== Utility functions =====

        // Convert the number in the string to the corresponding
        // Unicode character, e.g.
        //    decodeNumeric("64", 10)   --> "@"
        //    decodeNumeric("20ac", 16) --> "€"
        func decodeNumeric(_ string : String, base : Int) -> Character? {
            guard let code = UInt32(string, radix: base),
                let uniScalar = UnicodeScalar(code) else { return nil }
            return Character(uniScalar)
        }

        // Decode the HTML character entity to the corresponding
        // Unicode character, return `nil` for invalid input.
        //     decode("&#64;")    --> "@"
        //     decode("&#x20ac;") --> "€"
        //     decode("&lt;")     --> "<"
        //     decode("&foo;")    --> nil
        func decode(_ entity : String) -> Character? {

            if entity.hasPrefix("&#x") || entity.hasPrefix("&#X"){
                return decodeNumeric(entity.substring(with: entity.index(entity.startIndex, offsetBy: 3) ..< entity.index(entity.endIndex, offsetBy: -1)), base: 16)
            } else if entity.hasPrefix("&#") {
                return decodeNumeric(entity.substring(with: entity.index(entity.startIndex, offsetBy: 2) ..< entity.index(entity.endIndex, offsetBy: -1)), base: 10)
            } else {
                return characterEntities[entity]
            }
        }

        // ===== Method starts here =====

        var result = ""
        var position = startIndex

        // Find the next '&' and copy the characters preceding it to `result`:
        while let ampRange = self.range(of: "&", range: position ..< endIndex) {
            result.append(self[position ..< ampRange.lowerBound])
            position = ampRange.lowerBound

            // Find the next ';' and copy everything from '&' to ';' into `entity`
            if let semiRange = self.range(of: ";", range: position ..< endIndex) {
                let entity = self[position ..< semiRange.upperBound]
                position = semiRange.upperBound

                if let decoded = decode(entity) {
                    // Replace by decoded character:
                    result.append(decoded)
                } else {
                    // Invalid entity, copy verbatim:
                    result.append(entity)
                }
            } else {
                // No matching ';'.
                break
            }
        }
        // Copy remaining characters to `result`:
        result.append(self[position ..< endIndex])
        return result
    }
}

সুইফট 2:

// Mapping from XML/HTML character entity reference to character
// From http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references
private let characterEntities : [ String : Character ] = [
    // XML predefined entities:
    "&quot;"    : "\"",
    "&amp;"     : "&",
    "&apos;"    : "'",
    "&lt;"      : "<",
    "&gt;"      : ">",

    // HTML character entity references:
    "&nbsp;"    : "\u{00a0}",
    // ...
    "&diams;"   : "♦",
]

extension String {

    /// Returns a new string made by replacing in the `String`
    /// all HTML character entity references with the corresponding
    /// character.
    var stringByDecodingHTMLEntities : String {

        // ===== Utility functions =====

        // Convert the number in the string to the corresponding
        // Unicode character, e.g.
        //    decodeNumeric("64", 10)   --> "@"
        //    decodeNumeric("20ac", 16) --> "€"
        func decodeNumeric(string : String, base : Int32) -> Character? {
            let code = UInt32(strtoul(string, nil, base))
            return Character(UnicodeScalar(code))
        }

        // Decode the HTML character entity to the corresponding
        // Unicode character, return `nil` for invalid input.
        //     decode("&#64;")    --> "@"
        //     decode("&#x20ac;") --> "€"
        //     decode("&lt;")     --> "<"
        //     decode("&foo;")    --> nil
        func decode(entity : String) -> Character? {

            if entity.hasPrefix("&#x") || entity.hasPrefix("&#X"){
                return decodeNumeric(entity.substringFromIndex(entity.startIndex.advancedBy(3)), base: 16)
            } else if entity.hasPrefix("&#") {
                return decodeNumeric(entity.substringFromIndex(entity.startIndex.advancedBy(2)), base: 10)
            } else {
                return characterEntities[entity]
            }
        }

        // ===== Method starts here =====

        var result = ""
        var position = startIndex

        // Find the next '&' and copy the characters preceding it to `result`:
        while let ampRange = self.rangeOfString("&", range: position ..< endIndex) {
            result.appendContentsOf(self[position ..< ampRange.startIndex])
            position = ampRange.startIndex

            // Find the next ';' and copy everything from '&' to ';' into `entity`
            if let semiRange = self.rangeOfString(";", range: position ..< endIndex) {
                let entity = self[position ..< semiRange.endIndex]
                position = semiRange.endIndex

                if let decoded = decode(entity) {
                    // Replace by decoded character:
                    result.append(decoded)
                } else {
                    // Invalid entity, copy verbatim:
                    result.appendContentsOf(entity)
                }
            } else {
                // No matching ';'.
                break
            }
        }
        // Copy remaining characters to `result`:
        result.appendContentsOf(self[position ..< endIndex])
        return result
    }
}

10
এটি উজ্জ্বল, ধন্যবাদ মার্টিন! এইচটিএমএল সত্তাগুলির সম্পূর্ণ তালিকা সহ এখানে বর্ধিতকরণ রয়েছে: gist.github.com/mwaterfall/25b4a6a06dc3309d9555 আমি প্রতিস্থাপনগুলির দ্বারা তৈরি দূরত্ব অফসেটগুলি সরবরাহ করতে এটি সামান্যও অভিযোজিত করেছি। এটি এই প্রতিস্থাপনগুলির দ্বারা প্রভাবিত হতে পারে এমন কোনও স্ট্রিং বৈশিষ্ট্য বা সত্তাগুলির সঠিক সামঞ্জস্যের অনুমতি দেয় (উদাহরণস্বরূপ টুইটার সত্তা সূচকগুলি)।
মাইকেল জলপ্রপাত

3
@ মিশেল ওয়াটারফল এবং মার্টিন এটি দুর্দান্ত! একটি যাদুমন্ত্র মত কাজ করে! আমি সুইফট 2 পেস্টবিন . com/ জেএইচআরজে 6 এর জন্য এক্সটেনশনটি আপডেট করছি ধন্যবাদ!
সান্তিয়াগো

1
আমি এই উত্তরটি সুইফট 2 এর সাথে সামঞ্জস্যপূর্ণ রূপান্তরিত করেছি এবং এটিকে ব্যবহারের সহজতার জন্য স্ট্রিংএক্সটেনশন এইচটিএমএল নামে একটি কোকোপডে ফেলেছি । নোট করুন যে সান্টিয়াগোয়ের সুইফট 2 সংস্করণটি সংকলন সময়ের ত্রুটিগুলি ঠিক করেছে, তবে strtooul(string, nil, base)পুরোপুরি ব্যবহারের ফলে কোডটি সংখ্যার চরিত্র সত্তাগুলির সাথে কাজ না করার কারণ হয়ে দাঁড়ায় এবং ক্রাশটি যখন কোনও সত্তার কাছে আসে যখন এটি স্বীকৃত হয় না (কৃত্রিমভাবে ব্যর্থ হওয়ার পরিবর্তে)।
অ্যাডেলা চ্যাং

1
@ অ্যাডেলাচ্যাং: আসলে আমি আমার উত্তরটি ইতিমধ্যে সেপ্টেম্বরে 2015 সালে সুইফট 2-তে রূপান্তর করেছি It এটি এখনও সুইফট ২.২ / এক্সকোড .3.৩ সহ সতর্কতা ছাড়াই সংকলন করে। বা আপনি মাইকেল এর সংস্করণ উল্লেখ করা হয়?
মার্টিন আর

1
ধন্যবাদ, এই উত্তরের সাথে আমি আমার সমস্যাগুলি সমাধান করেছি: এনএসএট্রিবিউটড স্ট্রিং ব্যবহার করে আমার গুরুতর পারফরম্যান্স সমস্যা ছিল।
আন্দ্রেয়া মুগনাইনি

27

@ আকাশীবস্কি'র এক্সটেনশনের সুইফট 3 সংস্করণ ,

extension String {
    init(htmlEncodedString: String) {
        self.init()
        guard let encodedData = htmlEncodedString.data(using: .utf8) else {
            self = htmlEncodedString
            return
        }

        let attributedOptions: [String : Any] = [
            NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
            NSCharacterEncodingDocumentAttribute: String.Encoding.utf8.rawValue
        ]

        do {
            let attributedString = try NSAttributedString(data: encodedData, options: attributedOptions, documentAttributes: nil)
            self = attributedString.string
        } catch {
            print("Error: \(error)")
            self = htmlEncodedString
        }
    }
}

দুর্দান্ত কাজ করে। আসল উত্তরটি অদ্ভুত ক্র্যাশ ঘটিয়েছিল। আপডেটের জন্য ধন্যবাদ!
জিওহরনা

ফরাসি চরিত্রগুলির জন্য আমাকে utf16
Sébastien REMY

23

সুইফট 4


  • স্ট্রিং এক্সটেনশন গণিত ভেরিয়েবল
  • অতিরিক্ত গার্ড ছাড়া, কর, ধরা ইত্যাদি ...
  • ডিকোডিং ব্যর্থ হলে মূল স্ট্রিংগুলি প্রদান করে

extension String {
    var htmlDecoded: String {
        let decoded = try? NSAttributedString(data: Data(utf8), options: [
            .documentType: NSAttributedString.DocumentType.html,
            .characterEncoding: String.Encoding.utf8.rawValue
        ], documentAttributes: nil).string

        return decoded ?? self
    }
}

1
কি দারুন ! সুইফট 4 এর বাক্সের ঠিক বাইরে কাজ করে! ব্যবহার // এনকোড করা যাক = "দ্য উইকেন্ড & # 8216; পড়ন্ত কিং # & # 8217;" চূড়ান্ত স্ট্রিং = এনকোডড htmlDododed
নৈশত

2
আমি এই উত্তরের সরলতা পছন্দ করি। যাইহোক, এটি পটভূমিতে রান করার সময় ক্র্যাশ ঘটায় কারণ এটি মূল থ্রেডে চালানোর চেষ্টা করে।
জেরেমি হিকস

14

@ আকাশীবস্কি'র এক্সটেনশনের সুইফট 2 সংস্করণ ,

 extension String {
     init(htmlEncodedString: String) {
         if let encodedData = htmlEncodedString.dataUsingEncoding(NSUTF8StringEncoding){
             let attributedOptions : [String: AnyObject] = [
            NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
            NSCharacterEncodingDocumentAttribute: NSUTF8StringEncoding
        ]

             do{
                 if let attributedString:NSAttributedString = try NSAttributedString(data: encodedData, options: attributedOptions, documentAttributes: nil){
                     self.init(attributedString.string)
                 }else{
                     print("error")
                     self.init(htmlEncodedString)     //Returning actual string if there is an error
                 }
             }catch{
                 print("error: \(error)")
                 self.init(htmlEncodedString)     //Returning actual string if there is an error
             }

         }else{
             self.init(htmlEncodedString)     //Returning actual string if there is an error
         }
     }
 }

এই কোডটি অসম্পূর্ণ এবং সমস্ত উপায়ে এড়ানো উচিত। ত্রুটিটি সঠিকভাবে পরিচালনা করা হচ্ছে না। আসলে যখন একটি ত্রুটি কোড ক্রাশ হবে। কোনও ত্রুটি দেখা দিলে আপনার কোডটি কমপক্ষে শূন্য করার জন্য আপডেট করা উচিত। অথবা আপনি কেবল মূল স্ট্রিং দিয়ে দীক্ষা দিতে পারেন। শেষ পর্যন্ত আপনার ত্রুটিটি পরিচালনা করা উচিত। কোন ঘটনা না। কি দারুন!
ওয়ালহি

9

সুইফট 4 সংস্করণ

extension String {

    init(htmlEncodedString: String) {
        self.init()
        guard let encodedData = htmlEncodedString.data(using: .utf8) else {
            self = htmlEncodedString
            return
        }

        let attributedOptions: [NSAttributedString.DocumentReadingOptionKey : Any] = [
            .documentType: NSAttributedString.DocumentType.html,
            .characterEncoding: String.Encoding.utf8.rawValue
        ]

        do {
            let attributedString = try NSAttributedString(data: encodedData, options: attributedOptions, documentAttributes: nil)
            self = attributedString.string
        } 
        catch {
            print("Error: \(error)")
            self = htmlEncodedString
        }
    }
}

আমি "ত্রুটিযুক্ত ডোমেন = এনএসকোকাআররডোমাইন কোড = 259 পেয়েছি" ফাইলটি খুলতে পারেনি কারণ এটি সঠিক ফর্ম্যাটে নেই "" "যখন আমি এটি ব্যবহার করার চেষ্টা করি।" আমি মূল থ্রেডে ফুল ডু ক্যাচ চালালে এটি চলে যায়। আমি এনএসএট্রিবিউটেড স্ট্রিং ডকুমেন্টেশন যাচাই করে এটি পেয়েছি: "এইচটিএমএল আমদানিকারককে কোনও পটভূমি থ্রেড থেকে কল করা উচিত নয় (এটি বিকল্প অভিধানে ডকুমেন্ট টাইপ অন্তর্ভুক্ত করে html এর মান সহ) এটি মূল থ্রেডের সাথে সিঙ্ক্রোনাইজ করার চেষ্টা করবে, ব্যর্থ হবে, এবং সময় শেষ."
মিকডিজি

8
দয়া করে rawValueসিনট্যাক্স NSAttributedString.DocumentReadingOptionKey(rawValue: NSAttributedString.DocumentAttributeKey.documentType.rawValue)এবং NSAttributedString.DocumentReadingOptionKey(rawValue: NSAttributedString.DocumentAttributeKey.characterEncoding.rawValue)ভয়ঙ্কর। এটিকে .documentTypeএবং.characterEncoding
ভাদিয়ান

@ মিকডিজি - আপনি এই ত্রুটিটি সমাধান করার জন্য ঠিক কী করেছেন তা দয়া করে ব্যাখ্যা করতে পারেন? আমি এটি স্প্রেটিকভাবে পেয়ে যাচ্ছি।
রস বার্বিশ

@ রোসবার্বিশ - দুঃখিত রস, এটি অনেক আগে ছিল, বিশদটি মনে করতে পারে না। আপনি কি উপরের মন্তব্যে যা পরামর্শ দিয়েছেন তার অর্থ চেষ্টা করেছেন, অর্থাত্ মূল থ্রেডে পুরো ডু ক্যাচ চালানোর জন্য?
মিকডিজি

7
extension String{
    func decodeEnt() -> String{
        let encodedData = self.dataUsingEncoding(NSUTF8StringEncoding)!
        let attributedOptions : [String: AnyObject] = [
            NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
            NSCharacterEncodingDocumentAttribute: NSUTF8StringEncoding
        ]
        let attributedString = NSAttributedString(data: encodedData, options: attributedOptions, documentAttributes: nil, error: nil)!

        return attributedString.string
    }
}

let encodedString = "The Weeknd &#8216;King Of The Fall&#8217;"

let foo = encodedString.decodeEnt() /* The Weeknd ‘King Of The Fall’ */

রে "দ্য উইকেন্ড" : "উইকেন্ড" নয় ?
পিটার মর্টেনসেন

সিনট্যাক্স হাইলাইট করা অদ্ভুত দেখাচ্ছে, বিশেষত শেষ লাইনের মন্তব্যের অংশ। আপনি এটা ঠিক করতে পারবো?
পিটার মর্টেনসেন

"দ্য উইকেন্ড" একজন গায়ক এবং হ্যাঁ, এইভাবেই তাঁর নামের বানান।
ডাব্লুএলসি

5

আমি এইচটিএমএল চরিত্রের রেফারেন্স (যেমন উভয় ম্যাকোস এবং লিনাক্সের সার্ভার-সাইড সুইফট অ্যাপ্লিকেশনগুলির জন্য) থেকে আনসেস্কে / চালানোর জন্য একটি খাঁটি সুইফট util.০ ইউটিলিটি খুঁজছিলাম কিন্তু কোনও বিস্তৃত সমাধান খুঁজে পাইনি, তাই আমি নিজের প্রয়োগটি লিখেছি: https: //github.com/IBM-Swift/swift-html-entities

এই প্যাকেজটি, HTMLEntitiesএইচটিএমএল 4 নামক অক্ষরের রেফারেন্সের পাশাপাশি হেক্স / ডিসের সংখ্যার চরিত্রের রেফারেন্সগুলির সাথে কাজ করে এবং এটি ডাব্লু 3 এইচটিএমএল 5 বিশেষ অনুসারে বিশেষ সংখ্যার অক্ষর রেফারেন্সগুলি স্বীকৃতি দেবে ( &#x80;ইউরো চিহ্ন হিসাবে ইউনিকোপ করা উচিত (ইউনিকোডU+20AC ) এবং ইউনিকোড হিসাবে নয়) চরিত্রের জন্য U+0080, এবং U+FFFDআনসেস্কেপিংয়ের সময় নির্দিষ্ট বর্ণের রেফারেন্সগুলি প্রতিস্থাপনের অক্ষরের সাথে প্রতিস্থাপন করা উচিত )।

ব্যবহারের উদাহরণ:

import HTMLEntities

// encode example
let html = "<script>alert(\"abc\")</script>"

print(html.htmlEscape())
// Prints ”&lt;script&gt;alert(&quot;abc&quot;)&lt;/script&gt;"

// decode example
let htmlencoded = "&lt;script&gt;alert(&quot;abc&quot;)&lt;/script&gt;"

print(htmlencoded.htmlUnescape())
// Prints<script>alert(\"abc\")</script>"

এবং ওপির উদাহরণের জন্য:

print("The Weeknd &#8216;King Of The Fall&#8217; [Video Premiere] | @TheWeeknd | #SoPhi ".htmlUnescape())
// prints "The Weeknd ‘King Of The Fall’ [Video Premiere] | @TheWeeknd | #SoPhi "

সম্পাদনা করুন: HTMLEntitiesএখন সংস্করণ 2.0.0 অনুসারে এইচটিএমএল 5 নামক অক্ষর রেফারেন্স সমর্থন করে। স্পেক-কমপ্লায়েন্ট পার্সিংও প্রয়োগ করা হয়।


1
এটি সর্বাধিক জেনারিক উত্তর যা সর্বদা কাজ করে এবং মূল থ্রেডে চালানোর প্রয়োজন হয় না। এটি এমনকি সবচেয়ে জটিল এইচটিএমএল এড়ানো ইউনিকোড স্ট্রিং (যেমন (&nbsp;͡&deg;&nbsp;͜ʖ&nbsp;͡&deg;&nbsp;)) এর সাথেও কাজ করবে , অন্য উত্তরগুলির মধ্যে কেউ এটিকে পরিচালনা করে না।
স্টাফেন কপিন

5

সুইফট 4:

এইচটিএমএল কোড এবং নিউলাইন অক্ষর এবং একক উদ্ধৃতি দিয়ে পরিশেষে আমার পক্ষে কাজ করা সম্পূর্ণ সমাধান

extension String {
    var htmlDecoded: String {
        let decoded = try? NSAttributedString(data: Data(utf8), options: [
            .documentType: NSAttributedString.DocumentType.html,
            .characterEncoding: String.Encoding.utf8.rawValue
            ], documentAttributes: nil).string

        return decoded ?? self
    }
}

ব্যবহার:

let yourStringEncoded = yourStringWithHtmlcode.htmlDecoded

আমি তখন একক উদ্ধৃতি (উদাহরণস্বরূপ, না , না , এটি , ইত্যাদি) এবং নতুন লাইনের অক্ষরগুলি থেকে মুক্তি পেতে আরও কিছু ফিল্টার প্রয়োগ করতে হয়েছিল \n:

var yourNewString = String(yourStringEncoded.filter { !"\n\t\r".contains($0) })
yourNewString = yourNewString.replacingOccurrences(of: "\'", with: "", options: NSString.CompareOptions.literal, range: nil)

এটি মূলত এই অন্যান্য উত্তরের একটি অনুলিপি । আপনি যা কিছু করেছিলেন তা কিছু ব্যবহার যুক্ত করা যা যথেষ্ট সুস্পষ্ট।
rmaddy

কেউ এই উত্তরটিকে উঁচু করে তুলেছে এবং এটি সত্যিই দরকারী বলে মনে করেছে এটি আপনাকে কী বলে?
নাইশতা

@ নৈশতা এটি আপনাকে বলেছে যে সবার মতামত আলাদা এবং এটি ঠিক আছে
জোশ ওল্ফ

3

এটি আমার পদ্ধতির হবে। আপনি সত্তা অভিধানটি https://gist.github.com/mwaterfall/25b4a6a06dc3309d9555 মাইকেল জলপ্রপাতের উল্লেখ থেকে যোগ করতে পারেন ।

extension String {
    func htmlDecoded()->String {

        guard (self != "") else { return self }

        var newStr = self

        let entities = [
            "&quot;"    : "\"",
            "&amp;"     : "&",
            "&apos;"    : "'",
            "&lt;"      : "<",
            "&gt;"      : ">",
        ]

        for (name,value) in entities {
            newStr = newStr.stringByReplacingOccurrencesOfString(name, withString: value)
        }
        return newStr
    }
}

ব্যবহৃত উদাহরণ:

let encoded = "this is so &quot;good&quot;"
let decoded = encoded.htmlDecoded() // "this is so "good""

অথবা

let encoded = "this is so &quot;good&quot;".htmlDecoded() // "this is so "good""

1
আমি এটির
jrmgx

3

মার্জিত সুইফট 4 সমাধান

আপনি যদি একটি স্ট্রিং চান,

myString = String(htmlString: encodedString)

আপনার প্রকল্পে এই এক্সটেনশন যুক্ত করুন:

extension String {

    init(htmlString: String) {
        self.init()
        guard let encodedData = htmlString.data(using: .utf8) else {
            self = htmlString
            return
        }

        let attributedOptions: [NSAttributedString.DocumentReadingOptionKey : Any] = [
           .documentType: NSAttributedString.DocumentType.html,
           .characterEncoding: String.Encoding.utf8.rawValue
        ]

        do {
            let attributedString = try NSAttributedString(data: encodedData,
                                                          options: attributedOptions,
                                                          documentAttributes: nil)
            self = attributedString.string
        } catch {
            print("Error: \(error.localizedDescription)")
            self = htmlString
        }
    }
}

আপনি যদি সাহসী, তির্যক, লিঙ্ক, ইত্যাদি সহ কোনও এনএসএট্রিবিউটেড স্ট্রিং চান,

textField.attributedText = try? NSAttributedString(htmlString: encodedString)

আপনার প্রকল্পে এই এক্সটেনশন যুক্ত করুন:

extension NSAttributedString {

    convenience init(htmlString html: String) throws {
        try self.init(data: Data(html.utf8), options: [
            .documentType: NSAttributedString.DocumentType.html,
            .characterEncoding: String.Encoding.utf8.rawValue
            ], documentAttributes: nil)
    }

}

2

@ আইশাসের উত্তরের গণিত ভার্সন সংস্করণ

public extension String {
    /// Decodes string with HTML encoding.
    var htmlDecoded: String {
        guard let encodedData = self.data(using: .utf8) else { return self }

        let attributedOptions: [String : Any] = [
            NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
            NSCharacterEncodingDocumentAttribute: String.Encoding.utf8.rawValue]

        do {
            let attributedString = try NSAttributedString(data: encodedData,
                                                          options: attributedOptions,
                                                          documentAttributes: nil)
            return attributedString.string
        } catch {
            print("Error: \(error)")
            return self
        }
    }
}

1

সুইফট 4

func decodeHTML(string: String) -> String? {

    var decodedString: String?

    if let encodedData = string.data(using: .utf8) {
        let attributedOptions: [NSAttributedString.DocumentReadingOptionKey : Any] = [
            .documentType: NSAttributedString.DocumentType.html,
            .characterEncoding: String.Encoding.utf8.rawValue
        ]

        do {
            decodedString = try NSAttributedString(data: encodedData, options: attributedOptions, documentAttributes: nil).string
        } catch {
            print("\(error.localizedDescription)")
        }
    }

    return decodedString
}

একটি ব্যাখ্যা ক্রম হবে। উদাহরণস্বরূপ, পূর্ববর্তী সুইফট 4 টি উত্তর থেকে এটি কীভাবে আলাদা?
পিটার মর্টেনসেন

1

সুইফট 4.1 +

var htmlDecoded: String {


    let attributedOptions: [NSAttributedString.DocumentReadingOptionKey : Any] = [

        NSAttributedString.DocumentReadingOptionKey.documentType : NSAttributedString.DocumentType.html,
        NSAttributedString.DocumentReadingOptionKey.characterEncoding : String.Encoding.utf8.rawValue
    ]


    let decoded = try? NSAttributedString(data: Data(utf8), options: attributedOptions
        , documentAttributes: nil).string

    return decoded ?? self
} 

একটি ব্যাখ্যা ক্রম হবে। উদাহরণস্বরূপ, এটি পূর্ববর্তী উত্তরগুলি থেকে কীভাবে আলাদা? কোন সুইচ ৪.১ বৈশিষ্ট্য ব্যবহৃত হয়? এটি কি পূর্ববর্তী সংস্করণগুলিতে নয় কেবল সুইফটে 4.1 এ কাজ করে? অথবা এটি সুইফট ৪.১ এর পূর্বে কাজ করবে, সুইচ ৪.০ এ বলুন?
পিটার মর্টেনসেন

1

সুইফট 4

extension String {
    var replacingHTMLEntities: String? {
        do {
            return try NSAttributedString(data: Data(utf8), options: [
                .documentType: NSAttributedString.DocumentType.html,
                .characterEncoding: String.Encoding.utf8.rawValue
            ], documentAttributes: nil).string
        } catch {
            return nil
        }
    }
}

সাধারণ ব্যবহার

let clean = "Weeknd &#8216;King Of The Fall&#8217".replacingHTMLEntities ?? "default value"

আমি ইতিমধ্যে লোকদের আমার বলের মোড়ক খালি optionচ্ছিক সম্পর্কে অভিযোগ করতে শুনতে পাচ্ছি। আপনি যদি এইচটিএমএল স্ট্রিং এনকোডিং নিয়ে গবেষণা করছেন এবং আপনি কীভাবে সুইফ্ট বিকল্পগুলি মোকাবেলা করতে জানেন না, আপনি নিজের থেকে অনেক বেশি এগিয়ে।
নিরব

হ্যাঁ, সেখানে রয়েছে ( 1 নভেম্বর 22:37 এ সম্পাদিত এবং "সাধারণ ব্যবহার" বোঝা আরও শক্ত করে তোলা হয়েছে)
ক্রাইমফুল

1

সুইফট 4

আমি ডকুমেন্টএট্রিবিউটস ব্যবহার করে সমাধানটি সত্যিই পছন্দ করি। তবে, টেবিল ভিউ সেলগুলিতে ফাইলগুলি এবং / বা পার্সিংয়ের জন্য এটি খুব ধীর হতে পারে। আমি বিশ্বাস করতে পারি না যে অ্যাপল এর জন্য কোনও উপযুক্ত সমাধান সরবরাহ করে না।

কার্যকারণ হিসাবে, আমি এই স্ট্রিং এক্সটেনশনটি গিটহাবটিতে পেয়েছি যা নিখুঁতভাবে কাজ করে এবং ডিকোডিংয়ের জন্য দ্রুত।

সুতরাং যে পরিস্থিতিতে প্রদত্ত উত্তরটি ধীর হয়ে উঠছে , তার জন্য সমাধানটি এই লিঙ্কে প্রস্তাব দেখুন: https://gist.github.com/mwaterfall/25b4a6a06dc3309d9555

দ্রষ্টব্য: এটি HTML ট্যাগগুলি বিশ্লেষণ করে না।


1

আপডেট উত্তর সুইফট 3 এ কাজ করছে

extension String {
    init?(htmlEncodedString: String) {
        let encodedData = htmlEncodedString.data(using: String.Encoding.utf8)!
        let attributedOptions = [ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType]

        guard let attributedString = try? NSAttributedString(data: encodedData, options: attributedOptions, documentAttributes: nil) else {
            return nil
        }
        self.init(attributedString.string)
   }

0

উদ্দেশ্য গ

+(NSString *) decodeHTMLEnocdedString:(NSString *)htmlEncodedString {
    if (!htmlEncodedString) {
        return nil;
    }

    NSData *data = [htmlEncodedString dataUsingEncoding:NSUTF8StringEncoding];
    NSDictionary *attributes = @{NSDocumentTypeDocumentAttribute:     NSHTMLTextDocumentType,
                             NSCharacterEncodingDocumentAttribute:     @(NSUTF8StringEncoding)};
    NSAttributedString *attributedString = [[NSAttributedString alloc]     initWithData:data options:attributes documentAttributes:nil error:nil];
    return [attributedString string];
}

0

আসল ফন্ট আকার রূপান্তর সহ সুইফট 3.0 সংস্করণ

সাধারণত, আপনি যদি সরাসরি এইচটিএমএল বিষয়বস্তুকে কোনও বিশিষ্ট স্ট্রিংয়ে রূপান্তর করেন তবে ফন্টের আকার বাড়ানো হয়। আপনি এইচটিএমএল স্ট্রিংকে একটি বিশিষ্ট স্ট্রিংয়ে রূপান্তর করতে চেষ্টা করতে পারেন এবং পার্থক্যটি দেখতে আবার ফিরে আসতে পারেন।

পরিবর্তে, এখানে প্রকৃত আকার রূপান্তর যা ফন্টের আকার পরিবর্তন না করে তা নিশ্চিত করে, সমস্ত ফন্টে 0.75 অনুপাত প্রয়োগ করে:

extension String {
    func htmlAttributedString() -> NSAttributedString? {
        guard let data = self.data(using: String.Encoding.utf16, allowLossyConversion: false) else { return nil }
        guard let attriStr = try? NSMutableAttributedString(
            data: data,
            options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
            documentAttributes: nil) else { return nil }
        attriStr.beginEditing()
        attriStr.enumerateAttribute(NSFontAttributeName, in: NSMakeRange(0, attriStr.length), options: .init(rawValue: 0)) {
            (value, range, stop) in
            if let font = value as? UIFont {
                let resizedFont = font.withSize(font.pointSize * 0.75)
                attriStr.addAttribute(NSFontAttributeName,
                                         value: resizedFont,
                                         range: range)
            }
        }
        attriStr.endEditing()
        return attriStr
    }
}

0

সুইফট 4

extension String {

    mutating func toHtmlEncodedString() {
        guard let encodedData = self.data(using: .utf8) else {
            return
        }

        let attributedOptions: [NSAttributedString.DocumentReadingOptionKey : Any] = [
            NSAttributedString.DocumentReadingOptionKey(rawValue: NSAttributedString.DocumentAttributeKey.documentType.rawValue): NSAttributedString.DocumentType.html,
            NSAttributedString.DocumentReadingOptionKey(rawValue: NSAttributedString.DocumentAttributeKey.characterEncoding.rawValue): String.Encoding.utf8.rawValue
        ]

        do {
            let attributedString = try NSAttributedString(data: encodedData, options: attributedOptions, documentAttributes: nil)
            self = attributedString.string
        }
        catch {
            print("Error: \(error)")
        }
    }

দয়া করে rawValueসিনট্যাক্স NSAttributedString.DocumentReadingOptionKey(rawValue: NSAttributedString.DocumentAttributeKey.documentType.rawValue)এবং NSAttributedString.DocumentReadingOptionKey(rawValue: NSAttributedString.DocumentAttributeKey.characterEncoding.rawValue)ভয়ঙ্কর। এটি দিয়ে .documentTypeএবং.characterEncoding
ভাদিয়ান

এই সমাধানের পারফরম্যান্স ভয়ঙ্কর। পৃথক Caes জন্য এটি ঠিক আছে, ফাইল বিশ্লেষণ করার পরামর্শ দেওয়া হয় না।
ভিনসেন্ট

0

এইচটিএমএল স্ট্রিংয়ের দিকে নজর দিন - সুইফটে লেখা একটি লাইব্রেরি যা আপনার প্রোগ্রামকে স্ট্রিংগুলিতে এইচটিএমএল সত্তা যুক্ত করতে এবং মুছে ফেলার অনুমতি দেয়

সম্পূর্ণতার জন্য, আমি সাইট থেকে মূল বৈশিষ্ট্যগুলি অনুলিপি করেছি:

  • ASCII এবং UTF-8 / UTF-16 এনকোডিংয়ের জন্য সত্তা যুক্ত করে
  • 2100 টিরও বেশি নামযুক্ত সত্তা সরায় (যেমন &)
  • দশমিক এবং হেক্সাডেসিমাল সত্তা অপসারণ সমর্থন করে
  • সুইফট এক্সটেন্ডেড গ্রাফি ক্লাস্টারগুলিকে সমর্থন করার জন্য ডিজাইন করা হয়েছে (→ 100% ইমোজি-প্রুফ)
  • সম্পূর্ণ ইউনিট পরীক্ষিত
  • দ্রুত
  • নথিভুক্ত
  • উদ্দেশ্য-সি এর সাথে সামঞ্জস্যপূর্ণ

0

সুইফ্ট 5.1 সংস্করণ

import UIKit

extension String {

    init(htmlEncodedString: String) {
        self.init()
        guard let encodedData = htmlEncodedString.data(using: .utf8) else {
            self = htmlEncodedString
            return
        }

        let attributedOptions: [NSAttributedString.DocumentReadingOptionKey : Any] = [
            .documentType: NSAttributedString.DocumentType.html,
            .characterEncoding: String.Encoding.utf8.rawValue
        ]

        do {
            let attributedString = try NSAttributedString(data: encodedData, options: attributedOptions, documentAttributes: nil)
            self = attributedString.string
        } 
        catch {
            print("Error: \(error)")
            self = htmlEncodedString
        }
    }
}

এছাড়াও, আপনি যদি তারিখ, চিত্র, মেটাডেটা, শিরোনাম এবং বিবরণ বের করতে চান তবে আপনি আমার পোড নামক ব্যবহার করতে পারেন:

] [1]

পঠনযোগ্যতা কিট


এটি এমন কী যা এটি কিছু পূর্ববর্তী সংস্করণগুলি, সুইফট 5.0, সুইফট 4.1, সুইফট 4.0, ইত্যাদিতে কাজ করে না?
পিটার মর্টেনসেন

কালেকশনভিউগুলি ব্যবহার করে স্ট্রিং ডিকোড করার সময় আমি একটি ত্রুটি পেয়েছি
টুং ভু ডুক

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.