Преобразование Unicode в Windows-1251 с использованием XML (HTML) - PullRequest
8 голосов
/ 10 мая 2011

У меня есть XML-файл, и мне нужно создать HTML-файл с кодировкой Windows-1251, применив XSL-преобразование.Проблема заключается в том, что символы Unicode в XSL-файле не преобразуются в HTML-последовательность Unicode Escape, например, «ғ» во время преобразования XSL, только «?»знак написан вместо них.Как я могу попросить метод XslCompiledTransform.Transform сделать это преобразование?Или есть какой-либо метод для записи HTML-строки в HTML-файл Windows-1251 с применением HTML Unicode Escape Sequence, чтобы я мог выполнить XSL-преобразование в строку, а затем этим методом записать в файл с кодировкой Windows-1251 и с HTML-экранирование всех символов Юникода (что-то вроде Convert (" ғ ") вернет " ғ ")?

XmlReader xmlReader = XmlReader.Create(new StringReader("<Data><Name>The Wizard of Wishaw</Name></data>"));

XslCompiledTransform xslTrans = new XslCompiledTransform();
xslTrans.Load("sheet.xsl");

using (XmlTextWriter xmlWriter = new XmlTextWriter("result.html", Encoding.GetEncoding("Windows-1251")))
{
    xslTrans.Transform(xmlReader, xmlWriter); // it writes Windows-1251 HTML-file but does not escape unicode characters, just writes "?" signs
}

Спасибо всем за помощь!

ОБНОВЛЕНИЕ

Мой выходной тег конфигурации в XSL-файле:

<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />

Теперь я даже не надеюсь, что XSL удовлетворит мои потребности.Но мне интересно, что у меня нет никакого метода, чтобы проверить, является ли символ приемлемым указанной кодировкой.Что-то вроде

Char.IsEncodable('ғ', Encoding.GetEncoding('Windows-1251'))

Мое текущее решение - преобразовать все символы больше 127 (c> 127) в & # dddd;escape-строки, но мой начальник не удовлетворен решением, потому что источник сгенерированного HTML-файла не читается.

Ответы [ 5 ]

1 голос
/ 28 мая 2011

Обратите внимание, что XML является одновременно моделью данных и форматом сериализации. Данные могут использовать набор символов, отличный от сериализации этих данных.

Похоже, что основной причиной вашей проблемы является то, что ваш процесс сериализации пытается ограничить набор символов модели данных, тогда как вы хотели бы установить набор символов формата сериализации. Давайте рассмотрим пример: <band>Motörhead</band> и <band>Mot&#246;rhead</band> - это равные XML-документы. Они имеют одинаковую структуру и точно такие же данные. Из-за умного хэви-метала набор символов data является Unicode (или что-то большее, чем ASCII), но, поскольку используется ссылка на символ &#246;, набор символов из последней формы сериализации документа является ASCII. Чтобы обработать эти данные, ваши инструменты XML по-прежнему должны поддерживать Unicode в обоих случаях, но при использовании последней сериализации инструменты ввода-вывода и передачи файлов не обязательно должны распознавать Unicode.

Я предполагаю, что, сказав XMLTextWriter использовать кодировку Windows-1251, он, вероятно, на практике пытается ограничить набор символов данных символами, содержащимися в Windows-1251, отбрасывая все символы вне этого набора символов и вместо них пишется ?.

Однако, поскольку вы создаете свой XML-документ с помощью XSL-преобразования, вы можете управлять набором символов сериализации непосредственно в вашем XSLT-документе. Это делается путем добавления атрибута кодирования в элемент xsl: output. Измените его так, чтобы он выглядел следующим образом

<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" encoding="windows-1251"/>

Теперь процессор XSLT заботится о сериализации для сокращенного набора символов и выводит ссылку на символ для всех символов в данных, которые включены в windows-1251.

Если изменение набора символов данных действительно то, что вам нужно, то вам нужно обработать данные с помощью подходящей библиотеки преобразования символов, которая может угадать наиболее подходящий заменяющий символ (например, ö -> o).

0 голосов
/ 29 мая 2011

Самый безопасный и наиболее совместимый способ сделать это - указать encoding = "us-ascii" в вашем элементе xsl: output. Большинство процессоров XSLT поддерживают написание этой кодировки.

US-ASCII - это полностью безопасная кодировка, поскольку она является совместимым подмножеством UTF-8 (вы можете выбрать для маркировки выдаваемого XML кодировку «utf-8», поскольку это также будет верно: это может быть делается путем указания omit-xml-объявление = "да" для вашего xsl: output и вручную добавляя объявление "<? xml version = '1.0' encoding = 'utf-8'?>" к вашему выводу).

Этот подход работает, потому что при использовании кодировки US-ASCII сериализатор вынужден использовать механизм экранирования XML для символов, выходящих за пределы U + 007F, и поэтому будет генерировать их как ссылки на числовые символы ("& # .....; "форма).

При работе со средами, в которых требуются нестандартные кодировки, обычно является хорошим способом защиты для создания такого типа XML, поскольку он полностью совместим и работает на практике даже с некоторым программным обеспечением с ошибками.

0 голосов
/ 13 мая 2011

Правильным решением было бы написать файл в кодировке Unicode (например, UTF-8) и забыть о CP-1251 и всех других устаревших кодировках.

Но я будупредположим, что по какой-то причине это не вариант.

Лучшая альтернатива, которую я могу придумать, - это заменить символы в строке перед передачей ее в XmlReader.Вы должны использовать класс Encoding, чтобы преобразовать строку в массив байтов в CP-1251 и создать свой собственный механизм восстановления декодера.Затем резервный механизм может вставить escape-последовательности XML.Таким образом, вы гарантированно обрабатываете все (и в точности те) символы, которые отсутствуют в CP-1251.

Затем вы можете преобразовать массив байтов (в CP-1251) в обычную строку .NET (вUTF-16) и передайте его вашему XmlReader.Значения, которые должны быть экранированы, уже будут экранированы, поэтому окончательный файл должен быть записан правильно.

ОБНОВЛЕНИЕ

Я только что понял недостаток этого метода.XmlWriter также будет экранировать символы & как &amp;, поэтому сами экранированные символы будут отображаться в конечном документе, а не в символах, которые они представляют.

Для этого может потребоваться очень сложное решение! ДРУГОЕ ОБНОВЛЕНИЕ

Игнорировать это последнее обновление.Поскольку вы читаете строку как XML, escape-коды должны интерпретироваться правильно.Это то, что я получаю за то, что стараюсь публиковать сообщения быстрее, а не думать о проблеме!

Мое предлагаемое решение должно работать нормально.

0 голосов
/ 28 мая 2011

Вы пытались указать кодировку в xsl: output?(http://www.w3schools.com/xsl/el_output.asp)

0 голосов
/ 13 мая 2011

попробуйте дополнить свой xsl-файл правилами замены а-ля

<xsl:value-of select="replace(.,'&#1171;','&amp;#1171;')"/>

, вместо этого вы можете захотеть сделать это с помощью шаблонов регулярных выражений:

<xsl:value-of select="replace(.,'&#(\d+);','&amp;#$1;')"/>

проблема возникла с xmlсинтаксический анализатор, который заменяет числовую ссылку на сущность соответствующими символами Юникода до того, как произойдет преобразование.таким образом, неизвестные символы (соответственно '?') попадают в преобразованный документ.

надеюсь, это поможет,

с наилучшими пожеланиями,

carsten

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...