-1

I have a string like html string:

let string:String = "<a href="https://stackoverflow.com/1"> @username1 </a>
<a href="https://stackoverflow.com/2"> @username2 </a> 
<a href="https://stackoverflow.com/3"> @username3 </a>
<a href="https://stackoverflow.com/4" >@username4 </a>"

How to seprate them to get each URL and username?
Like this

[ https://stackoverflow.com/2 : @username2 ]

Sorry I don't know what is the best way to fix it.
Thanks.

tolerate_Me_Thx
  • 387
  • 2
  • 7
  • 21
  • 5
    Don't use regex: [H̸̡̪̯ͨ͊̽̅̾̎Ȩ̬̩̾͛ͪ̈́̀́͘ ̶̧̨̱̹̭̯ͧ̾ͬC̷̙̲̝͖ͭ̏ͥͮ͟Oͮ͏̮̪̝͍M̲̖͊̒ͪͩͬ̚̚͜Ȇ̴̟̟͙̞ͩ͌͝S̨̥̫͎̭ͯ̿̔̀ͅ](https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags) – ctwheels Jan 11 '18 at 16:25
  • why? or have any good suggest? – tolerate_Me_Thx Jan 11 '18 at 16:26
  • You can use `NSAttributedString` (look how to convert HTML String to NSAttributedString), then on it `.enumerateAttribute(.link ...)` and fill your whatever the structure you need. – Larme Jan 11 '18 at 16:33
  • 1
    It's important to note here that the recommendation against regex is really "don't try to do arbitrary HTML parsing with regex." If you have a small, specific string that *happens* to be HTML, but may vary a bit such that static string parsers are hard, regex is fine and is not Zalgo-inducing. If it does not vary at all, then @ColGraff's answer is better. – Rob Napier Jan 11 '18 at 17:01

1 Answers1

1

Possible solution:

let str:String = "<a href=\"https://stackoverflow.com/1\"> @username1 </a><a href=\"https://stackoverflow.com/2\"> @username2 </a><a href=\"https://stackoverflow.com/3\"> @username3 </a><a href=\"https://stackoverflow.com/4\" >@username4 </a>"

Create AttributedString from the HTML String

let attributedString = try NSAttributedString(data: str.data(using: .utf8)!,
                                              options: [.documentType: NSAttributedString.DocumentType.html],
                                              documentAttributes: nil)

I used URL objects for the key, but could be String (then in the closure you have to change it, using result.append([link.absoluteString:subStr]) instead)

var result = [[URL:String]]()

attributedString.enumerateAttribute(.link, in: NSRange(location: 0, length: attributedString.string.count), options: []) { (value, range, pointer) in
    if let link = value as? URL {
        let subStr = (attributedString.string as NSString).substring(with: range)
        result.append([link:subStr])
    }
}

print("result: \(result)")

Output:

$>result: [["https://stackoverflow.com/1": "@username1 "], ["https://stackoverflow.com/2": "@username2 "], ["https://stackoverflow.com/3": "@username3 "], ["https://stackoverflow.com/4": "@username4 "]]
Larme
  • 24,190
  • 6
  • 51
  • 81