Страница 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?