У меня есть устаревшее приложение в Perl, которое, скорее всего, обрабатывает XML, закодированный в UTF-8
, и которому необходимо хранить некоторые данные этого XML в некоторой базе данных, которая использует windows-1252
по историческим причинам. Да, эта установка не может поддерживать все возможные символы стандарта Unicode, но на практике мне все равно это не нужно и я могу попытаться быть разумно совместимым.
Конкретной проблемой в настоящее время является файл, содержащий LATIN SMALL LETTER U, COMBINING DIAERESIS
(U+0075 U+0308
), что заставляет Perl разбить существующую кодировку строки Unicode на windows-1252
со следующим исключением:
"\ x {0308}" не отображается на cp1252
Мне удалось обойти эту проблему, используя Unicode :: Normalize :: NFKC , который создает символ U+00FC
(ü
), который прекрасно отображается на windows-1252
. Это приводит к некоторой другой проблеме, например, например. в случае символа VULGAR FRACTION ONE HALF
(½
, U+00BD
), потому что NFKC
создает для этого DIGIT ONE, FRACTION SLASH, DIGIT TWO
(1/2
, U+0031 U+2044 U+0032
) и Perl снова умирает:
"\ x {2044}" не сопоставляется с cp1252
Согласно правилам нормализации , это прекрасно для NFKC
. Я использовал это, потому что я думал, что это даст мне наиболее совместимый результат, но это было неправильно. Использование NFC
вместо этого решило обе проблемы, поскольку оба символа обеспечивают нормализацию , совместимую с windows-1252
в этом случае.
Этот подход становится еще более проблематичным для символов, для которых нормализация, совместимая с windows-1252
, в целом доступна, отличается только от NFC
. Одним из примеров является LATIN SMALL LIGATURE FI
(fi
, U+FB01
). Согласно правилам нормализации , его представление после NFC
несовместимо с windows-1252
, а при использовании NFKC
на этот раз два символа совместимы с windows-1252
: fi
(U+0066 U+0069
) .
Мой нынешний подход заключается в том, чтобы просто попробовать кодировать как windows-1252
как есть, если это не удастся, я использую NFC
и повторить попытку, если это не удастся, я использую NFKC
и повторить попытку, и если это не удастся, я Я сдаюсь на данный момент. Это работает в тех случаях, с которыми я сейчас имею дело, но, очевидно, не работает, если все три символа из моих примеров выше присутствуют в строке одновременно. Тогда всегда есть один символ, что приводит к windows-1252
-совместимому выводу, независимо от порядка NFC
и NFKC
. Вопрос только в том, какой персонаж сломается, когда.
НО важным моментом является то, что каждый символ сам по себе может быть нормализован к чему-то, совместимому с windows-1252
. Только кажется, что нет единого решения.
Итак, есть ли какой-то API, который мне не хватает, который уже конвертируется наиболее обратно совместимым способом?
Если нет, то какой подход мне нужно реализовать самому, чтобы поддерживать все вышеперечисленные символы в одной строке?
Звучит так, будто мне нужно обработать каждую строку Unicode-символа Unicode-символом, индивидуально нормализовать с тем, что наиболее совместимо с windows-1252
, и затем снова объединить результаты. Есть ли какой-нибудь инкрементный синтаксический анализатор Unicode-символов, который уже занимается комбинированием символов и прочего? Обрабатывает ли это уже простое регулярное выражение на основе Unicode?
Unicode::Normalize
предоставляет дополнительные функции для работы с частичными строками и тому подобным, но я должен признать, что в настоящее время я не до конца понимаю их назначение. Примеры также фокусируются на конкатенации, но, насколько я понимаю, мне сначала понадобится некоторый анализ, чтобы можно было по-разному нормализовать отдельные символы.