1

I've got a text which has some HTML tags in it. Something like this:

Lorem lipsum <a href="www.example.com"> lorem lipsum.

I want to insert the text style=\"text-decoration: none\ right at the end of the HTML tag so that the link has no underline.

I've got a regex pattern that finds the HTML tag: <\s*a[^>]*>(.*?)<\s*/\s*a>

I have the following code to get the regex matches in the paragraph text and to calculate the position of the last character in the HTML tag:

let range = NSRange(location: 0, length: paragraph.utf16.count)
let regex = try! NSRegularExpression(pattern: "<\\s*a[^>]*>(.*?)<\\s*/\\s*a>")
let allMatches = regex.matches(in: paragraph, options: [], range: range)
let lastCharacter = allMatches[0].range.location + allMatches[0].range.length

How can I insert the string style=\"text-decoration: none\ at that position?

I tried something like this:

let newParagraph = paragraph.insert(" style=\"text-decoration: none\"", at: lastCharacter)

However Xcode says that the first parameter in the insert method has to be a character, not a string.

2
  • Did you try the insertString method? Commented Jul 17, 2018 at 6:56
  • Is this an objective-c method? Xcode won't autocomplete this method. Commented Jul 17, 2018 at 6:58

1 Answer 1

1

In my solution I use a regex finding everything between <and >to find the whole HTML tag. After the tag is found I use the replacingOccurrences(of:with:) method to

  1. replace the closing tag’s bracket with the additional style= attribute (plus a closing bracket) to create the modified tag,
  2. replace the original tag with the modified tag.

Here’s the code:

let string = "Lorem lipsum <a href=\"www.example.com\"> lorem lipsum <a href=\"www.somewhereelse.com\"> dolor sit amet."
let insertString = " style=\"text-decoration: none\">"
var modifiedString = string

let regex = try! NSRegularExpression(pattern: "<.*?>")
let range = NSRange(string.startIndex..., in: string)
let matches = regex.matches(in: string, range: range)
let tags = matches.map { String(string[Range($0.range, in: string)!]) }

for tag in tags {
    let newTag = tag.replacingOccurrences(of: ">", with: insertString)
    modifiedString = modifiedString.replacingOccurrences(of: tag, with: newTag)
}

print(modifiedString)

The updated code now uses a loop to replace all tags with the enhanced tags as per your requirement. For this to work you will have to change the regex to non-greedy: <.*?> instead of <.*>.

Sign up to request clarification or add additional context in comments.

6 Comments

@WalterBeiter: Ok, I've just updated my code accordingly.
I tried implementing your code. I'Ve stumbled upon the short regex pattern. I only want this to happen for <a> tags – links in html. Thats why I had this longer regex pattern.
Sure. Just make sure your pattern is non-greedy so that you get an array of tags. So (without having tested) the pattern <a.*?> should do—or your pattern, of course ;-).
Cool! Glad I could help.
matches is an array of NSTextCheckingResult items returned from the regex queries. The map command traverses all array elements, exposing each element through the $0 placeholder. So $0.range effectively means <first regex match>.range, <second regex match>.range, ... NSTextCheckingResult.range yields the range of the regex match inside the search string. String(...) extracts this range from the string. map returns an array of whatever happens inside {and }, being Stringin our example. I. e. you get an array of strings each representing one of the regex matches.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.