Difference between revisions of "XML Decoders/ru"
(→Функция Decode: more improvements) |
(→Доступные декодеры: improved translation) |
||
Line 9: | Line 9: | ||
=== Доступные декодеры === | === Доступные декодеры === | ||
− | В | + | В состав пакета fcl-xml входит декодер, использующий библиотеку libiconv. Он имеет две разновидности: |
1. Модуль '''xmliconv.pas''', который использует существующий пакет iconvenc и предназначен для операционных систем Linux, FreeBSD и Darwin. | 1. Модуль '''xmliconv.pas''', который использует существующий пакет iconvenc и предназначен для операционных систем Linux, FreeBSD и Darwin. | ||
− | 2. Модуль '''xmliconv_windows.pas''' для Windows. Он связан с библиотекой iconv.dll, которую | + | 2. Модуль '''xmliconv_windows.pas''' для Windows. Он связан с библиотекой iconv.dll "родной" сборки (т.е. не из состава cygwin или mingw), которую придется распространять вместе с приложением. |
=== Структура декодера === | === Структура декодера === |
Revision as of 16:56, 18 January 2010
│
English (en) │
español (es) │
русский (ru) │
中文(中国大陆) (zh_CN) │
XML декодеры
Дополнение к XML_Tutorial/ru.
Начиная с ревизии SVN 12582, XMLReader в состоянии обработать данные в любой кодировке при использовании внешних декодеров. Эта статья - краткое описание, как оно работает.
Доступные декодеры
В состав пакета fcl-xml входит декодер, использующий библиотеку libiconv. Он имеет две разновидности:
1. Модуль xmliconv.pas, который использует существующий пакет iconvenc и предназначен для операционных систем Linux, FreeBSD и Darwin.
2. Модуль xmliconv_windows.pas для Windows. Он связан с библиотекой iconv.dll "родной" сборки (т.е. не из состава cygwin или mingw), которую придется распространять вместе с приложением.
Структура декодера
Интерфейс с внешними декодерами сделан в простом процедурном стиле. Для написания декодера по существу используют следующие три процедуры:
GetDecoder
Decode
Cleanup
(опционально)
Вот краткое описание:
Функция GetDecoder
function GetDecoder(const AEncoding: string; out Decoder: TDecoder): Boolean; stdcall;
Во время инициализации программы декодер необходимо зарегистрировать путем вызова процедуры XMLRead.RegisterDecoder
, которой в качестве параметра передаётся функция GetDecoder
.
Если в процессе чтения XMLReader обнаруживает кодировку, которую он не может обработать сам, то он вызывает все зарегистрированные функции GetDecoder
в том же порядке, в котором они были зарегистрированы, до тех пор, пока одна из них не возвратит True.
Параметры функции GetDecoder
- название кодировки и запись типа TDecoder
, которую должна заполнить функция. Название кодировки содержит только символамы из множества ['A'..'Z', 'a'..'z', '0'.. '9', '.', '-,' _'], сравнивать названия кодировок следует независимо от регистра. Если декодер поддерживает данную кодировку, функция должна установить по крайней мере поле Decode
в записи Decoder и возвратить True. Установка остальных полей записи Decoder
не является обязательной.
Процедура Cleanup
procedure Cleanup(Context: Pointer); stdcall;
Если функция GetDecoder
установила поле Decoder.Cleanup
, то указанная процедура будет вызвана один раз, когда чтение объекта завершено и декодер больше не нужен. Как следует из названия, декодер должен освободить все занятые ресурсы.
Значение Decoder.Context
передается в качестве аргумента процедур Decode
и Cleanup
при каждом вызове. XMLReader сам не присваивает значение этому полю.
Функция Decode
function Decode(Context: Pointer; InBuf: PChar; var InCnt: Cardinal; OutBuf: PWideChar; var OutCnt: Cardinal): Integer; stdcall;
Функция Decode
выполняет основную работу. Она должна преобразовать входные данные, указатель на которые находится в InBuf
, в UTF-16 и записать перевод в буфер, на который указывает OutBuf
. Размер входного буфера находится в InCnt
, а размер буфера вывода находится в OutCnt
.
Важное замечание: значение InCnt
выражено в bytes, в то время как OutCnt
- в WideChars.
Функция должна уменьшить InCnt
and OutCnt
в соответствии с количеством обработанных данных. Каждый обработанный символ уменьшает OutCnt
на единицу (или на 2 в случае, если в буфер записывается суррогатная пара); то, на сколько уменьшается InCnt
, зависит от входной кодировки.
Функция не должна делать каких-либо предположений о начальном размере буферов: для примера, парсер может вызвать Decode
с недостаточной длиной входного буфера. В этом случае Decode
должна возвратить 0, индицируя о том, она ничего не декодировала, после чего парсер прочитает дополнительные входные данные и вызовет Decode
снова.
Функция должна возвращать положительный результат, если она что-то обработала, ноль - если нет (по причине отсутствия места во входном или выходном буфере), и отрицательное значение в случае, если входные данные содержат недопустимую последовательность. В настоящее время любое отрицательное значение просто прерывает чтение с сообщением об ошибке декодирования, но в дальнейшем, возможно, будут определены разновидности ошибок.
В случае обнаружения ошибки во входных данных декодер все равно должен уменьшить значение OutCnt
на количество успешно обработанных символов. Это позволяет парсеру сообщать точное расположение ошибки в тексте.