Как декодировать x20x20background в Swift?

#html #swift

Вопрос:

Я хочу иметь возможность декодировать строку в формате x20, x3c, которую я получаю из HTML, в Swift. Я попробовал это на python и смог сделать это с помощью этого кода

 soupData = dom
encodedSoupData = soupData.encode('utf8')
soupData = encodedSoupData.decode('unicode_escape')
 

где dom x20x20backgroundx2Dsizex3Ax20Contain

Приведенный выше код возвращает

   background-size: Contain
 

То, что я сделал в Swift сейчас, это:

  • Преобразуйте эту строку в Data кодер utf8.
  • Попробуйте декодировать данные обратно String с помощью декодера unicode.

До сих пор у меня ничего не получалось. Любая помощь была бы очень признательна. Спасибо!

Комментарии:

1. Контролируете ли вы источник этих данных? Насколько я помню, это нестандартная схема кодирования. Было бы лучше просто иметь правильную строку Юникода с самого начала

2. К сожалению, я этого не делаю 🙁

Ответ №1:

После долгих экспериментов я, наконец, смог решить этот вопрос.

Во — первых, мы добавляем расширение String для декодирования символов Юникода:

 extension String {
    var decodingUnicodeCharacters: String { applyingTransform(.init("Hex-Any"), reverse: false) ?? "" }
}
 

Затем мы создаем регулярное выражение с 2 группами захвата-

  • Первая группа-это экранирующий символ x
  • Вторая группа-это 2 буквенно-цифровых символа после x. (В моем примере буквы написаны в верхнем регистре.
 let pattern = #"(\x)?([0-9A-F]{2})"#
guard let regex = try? NSRegularExpression(pattern: pattern, options: .anchorsMatchLines) else { return }
 

Затем мы находим длину совпадающей строки, а затем используем stringByReplacingMatches вкл NSRegularExpression ., чтобы заменить совпадения в диапазоне шаблоном.

Шаблон-это то, что становится интересным. После долгих исследований я обнаружил, что преобразование строки xxx в u00XX является единственным шаблоном, который помогает в декодировании строки.

 let testString: String = #"x20x20backgroundx2Dsizex3Ax20Contain"#
let stringRange = NSRange(location: 0, length: testString.utf16.count)
let result = regex.stringByReplacingMatches(in: testString, range: stringRange, withTemplate: #"\u00$2"#)
 

Теперь просто нанесите decodingUnicodeCharacters на result строку.

 print(result.decodingUnicodeCharacters) //Outputs: "  background-size: Contain"