Страница 1 из 2
ReadXMLFile неверная кодировка
Добавлено:
27.04.2009 19:10:40
baiguzov
Функцией ReadXMLFile читаю xml-файл в кодировке UTF-8, первая строка файла
<?xml version="1.0" encoding="UTF-8"?>
но при чтении функцией node.Attributes.GetNamedItem('attribute_name').NodeValue данные приходят в кодировке cp1251. Можно ли это как-то исправить? Может быть где-то можно указать чтобы не xml не конвертировался?
Или как альтернатива подскажите чем ещё можно прочитать xml файл в utf-8 кодировке?
PS Пробовал искать ответ на этом форуме и на англоязычном, а также гуглил и яндексил, но ответа увы не нашёл.
Re: ReadXMLFile неверная кодировка
Добавлено:
27.04.2009 20:03:24
Sergei I. Gorelkin
Все данные в DOM имеют тип widestring и кодировку utf-16, вне зависимости от того, что написано в первой строке файла.
Если свойства DOM присваивать переменным типа AnsiString, то компилятор добавит неявное преобразование в кодовую страницу системы, в случае русской Windows это будет cp1251.
Поэтому лучше работать с переменными типа WideString (при этом не будет перекодировок, код будет компактнее и быстрее), или, если нужно таки получить utf-8 - то использовать функции utf8encode() и utf8decode().
Re: ReadXMLFile неверная кодировка
Добавлено:
27.04.2009 20:15:26
shade
Жаль, что FPC не различает типы AnsiString и UTF8String
Re: ReadXMLFile неверная кодировка
Добавлено:
27.04.2009 20:29:22
baiguzov
Вот этот вариант UTF8Encode(node.Attributes.GetNamedItem('attribute_name').NodeValue) выдаёт результат в UTF-8. Спасибо за совет.
Re: ReadXMLFile неверная кодировка
Добавлено:
17.08.2009 13:58:17
Vladimir
Столкнулся с аналогичной проблемой и не только я
http://www.lazarus.freepascal.org/index.php/topic,6409.0.html .
Обрабатываю xml в UTF-8, записываю в переменную WideString, например, значение атриубута с русскими символами, получаю текст в win-1251
...
var
NodeText:WideString;
begin
...
NodeText:=CNode.Attributes.GetNamedItem('name').TextContent;
...
end;
Приходится перекодировать в UTF-8 с моиощью UTF8Encode(). Как я понял, это баг последних версий Lazarus, проблема не в компоненте. Или я ошибаюсь? Баг, конечно, крайне неприятный
Re: ReadXMLFile неверная кодировка
Добавлено:
17.08.2009 14:23:14
Mr.Smart
Это не баг!
Непосредственное присваивания строки WideString к String преобразует символы юникода к локальной однобайтовой кодеровке системы.
В данном случае к кодеровке Win-1251.
Для преобразования в UTF-8 существуют специальные функции.
Re: ReadXMLFile неверная кодировка
Добавлено:
17.08.2009 14:25:06
Vladimir
А где здесь присваивание WideString к String? переменная в которую записывается значение атрибута типа WideString
Re: ReadXMLFile неверная кодировка
Добавлено:
17.08.2009 14:27:20
Mr.Smart
Vladimir писал(а):А где здесь присваивание WideString к String? переменная в которую записывается значение атрибута типа WideString
Тогда вопрос. Как вы определили, что у вас в переменной именно кодировка Win-1251?
Re: ReadXMLFile неверная кодировка
Добавлено:
17.08.2009 14:37:23
Vladimir
Под отладчиком посмотрел. Кроме того при попытке присвоить значение этой переменной свойству любого компонента имеем в этом свойстве пустую строку (собственно так проблема и обнаружилась), после перекодировки с помощью UTF8Encode() тоже свойство содержит нормальный русский текст
Re: ReadXMLFile неверная кодировка
Добавлено:
17.08.2009 14:38:44
Mr.Smart
WideString - это 2-х байтная строка UCS-2
UTF8String = AnsiString = String - это одно байтная строка. В которой текст хранится либо в кодировке UTF-8 либо в ANSI.
Re: ReadXMLFile неверная кодировка
Добавлено:
17.08.2009 14:49:22
Vladimir
кодировка UTF-8 содержит, насколько мне известно и однобайтные и многобайтные символы.
И какой из этого вывод? Какого типа должна быть переменная, чтобы избежать преобразования в локаль системы?
Re: ReadXMLFile неверная кодировка
Добавлено:
17.08.2009 14:53:00
Mr.Smart
Преобразование строк:
WideString(Unicode,UCS2)<->AnsiПростое присваивание
- Код: Выделить всё
...
var
sw: WideString;
sa: String;
...
sa:=sw;
...
Unicode <-> UTF-8- Код: Выделить всё
UTF8Encode()
UTF8Decode()
Ansi <-> UTF-8- Код: Выделить всё
AnsiToUTF8()
UTF8ToAnsi()
p.s. Все строки LCL используют кодировку UTF-8!
Добавлено спустя 8 минут 50 секунд:Vladimir писал(а):кодировка UTF-8 содержит, насколько мне известно и однобайтные и многобайтные символы.
Содержит, но особенность этой кодировки в том, что символ с кодом #0 неможет встретится поэтому для хранения используется обычный тип
StringVladimir писал(а):И какой из этого вывод? Какого типа должна быть переменная, чтобы избежать преобразования в локаль системы?
В данный момент для преобразования в UTF8 вам недостаточно будет просто присвоить одну строку другой:
- Код: Выделить всё
...
var
w: WideString;
u: UTF8String; // можно использовать и AnsiString и String
...
u:=w; // Вызовет неявное преобразование Unicode->Ansi
u:=UTF8Encode(w); // Преобразование Unicode->UTF-8
...
p.s. В будущем обещают выделить тип UTF8String в отдельный. И возможно появится неявное преобразование Unicode в UTF-8 и Ansi в UTF-8 простым присваиванием! Но это будет ещё нескоро...
Re: ReadXMLFile неверная кодировка
Добавлено:
17.08.2009 15:09:09
Vladimir
Как преобразовать в общем-то понятно. Не ясно, почему возникает необходимость преобразования? Потому что свойства LCL в UTF-8, а WideString - это UTF-16 ?
В целом выглядит странно. Парсим файл в UTF-8 (другие кодировки ReadXMLFile() не принимает, в итоге его же элементы перекодируем в тот же UTF-8
Добавлено спустя 11 минут 48 секунд:Да, посмотрел, в частности параметр TTreeNodes.AddChild в который я передаю значение атрибута - типа string. Спасибо, Mr.Smart!
Текущую реализацию работы с xml в лазарус сложно признать удобной
Re: ReadXMLFile неверная кодировка
Добавлено:
17.08.2009 16:11:22
Sergei I. Gorelkin
Vladimir писал(а):Как преобразовать в общем-то понятно. Не ясно, почему возникает необходимость преобразования? Потому что свойства LCL в UTF-8, а WideString - это UTF-16 ?
Да, поэтому.
Модуль для работы с xml написан в соответствии со спецификацией w3.org, которая предусматривает использование строк с двухбайтными элементами. Ноги этой спецификации растут откуда-то из мира java, насколько я понимаю.
ReadXMLFile понимает не только utf-8, но и utf-16 и iso8859-1, а при условии подключения к программе модуля xmliconv (в винде - xmliconv_windows) - и все остальные кодировки.
Re: ReadXMLFile неверная кодировка
Добавлено:
17.08.2009 20:14:41
Vladimir
Sergei I. Gorelkin писал(а):Модуль для работы с xml написан в соответствии со спецификацией w3.org, которая предусматривает использование строк с двухбайтными элементами. Ноги этой спецификации растут откуда-то из мира java, насколько я понимаю.
Спасибо! Выбор 2-х байтовых строк вполне логичен, универсальность это - хорошо. Только учитывая, обсуждаемую склонность компилятора перекодировать текст в локаль, получается несколько неуклюже, и не очевидно, особенно для новичков.
Если я правильно понял, переменные типа string могут содержать как одно так и двух байтовый текст, почему бы не рассмотреть вариант возврата значений в виде string, но в 2-х байтовом виде? Или принципиально использование именно UTF-16?