Sign in Join
Wiki copytemporary

XML Decoders/es: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: XML Decoders/es

OldNewLine
1+## XML Decodificadores
2+
3+   A partir de la revisión de SVN 12582, el lector de XML es capaz de procesar los datos en cualquier codificación mediante el uso de descodificadores externos. Lo que sigue es una breve descripción de cómo funciona.
4+
5+### Decodificadores disponibles
6+
7+   En la actualidad, un decodificador que utiliza libiconv está disponible. Tiene dos implementaciones distintas. La primera, en la unidad**xmliconv.pas**, utiliza el paquete iconvenc existente y es compatible con Linux, FreeBSD y Darwin. La segunda, en la unidad **xmliconv_windows.pas**, es para Windows. Enlaza a la iconv.dll que debes distribuir con la aplicación.
8+
9+### Estructura del decodificador
10+
11+   La interacción con los decodificadores externos se hace mediante procedimiento sencillo. Escribir el decodificador es esencialmente escribir la implementación de los tres procedimientos siguientes:
12+
13+1. `GetDecoder`
14+2. `Decode`
15+3. `Cleanup` (optional)
16+
17+   Aquí una breve descripción del funcionamiento con un decodificador externo:
18+
19+#### GetDecoder
20+
21+``` pascal
22+function GetDecoder(const AEncoding: string; out Decoder: TDecoder): Boolean; stdcall;
23+```
24+
25+   En el momento de la iniciación del programa, el decodificador se registra llamando al procedimiemto `XMLRead.RegisterDecoder` y pasando la función `GetDecoder` como argumento.    Cada vez que el lector se encuentra con una etiqueta de codificación que no controla internamente, llama a todas las funciones `GetDecoder` registradas en el mismo orden en que se registraron, hasta que una de ellas devuelve **true**.    Los argumentos de la función `GetDecoder` son el nombre de la codificación y el registro `TDecoder` que la función debe llenar. El nombre de codificación se limita a los caracteres de rango \['Z' .. 'A ', 'a' .. 'z', '0 '.. '9',, '.' '-','_'\], y no distingue entre mayúsculas y minúsculas. Si el decodificador es compatible con la codificación dada, la función debe establecer al menos el miembro `Decode` del registro suministrado y devolver *True*. Cumplimentar otros miembros de `Decoder` es opcional.
26+
27+#### Cleanup
28+
29+``` pascal
30+ procedure Cleanup(Context: Pointer); stdcall;
31+```
32+
33+   Si `GetDecoder` establece el miembro `Decoder.Cleanup`, se llamará por el lector de una vez, después de la transformación de la entidad actual esté acabada. Como sugiere el nombre, el decodificador debe liberar todos los recursos asignados.
34+
35+   El valor de `Decoder.Context` se pasa a los procedimientos `Decode` y `Cleanup` cada vez que es llamado. El lector no da ningún significado a este valor.
36+
37+#### Decode
38+
39+``` pascal
40+ function Decode(Context: Pointer; InBuf: PChar; var InCnt: Cardinal; OutBuf: PWideChar; var OutCnt: Cardinal): Integer; stdcall;
41+```
42+
43+   La función `Decode` hace el trabajo principal. Convierte los datos de entrada apuntados por `inbuf` a UTF-16 formato de boble byte de la plataforma actual y la pone en `outbuf`. El tamaño del espacio de entrada se muestra en `InCnt`, el espacio disponible en el espacio de salida se encuentra en `OutCnt`.
44+
45+   Una diferencia importante a destacar es que `InCnt` se da en **bytes**, mientras que `OutCnt` está en **WideChars**.
46+
47+   La función debe decrementar `InCnt` y `OutCnt` de acuerdo a la cantidad de datos procesados. Cada carácter procesados disminuye `OutCnt` en una unidad (o dos en caso de que el sustituto escrito sea doble), la cantidad a disminuir de `InCnt` depende de la codificación real.
48+
49+   No debe hacerse níngun presunción sobre el tamaño inicial de la memoria de trabajo: por ejemplo, el lector puede llamar al decodificador con sólo unos pocos bytes en la memoria de entrada. La función decodificador debe volver cero para indicar que nada se ha procesado, y el lector pondrá más datos en la entrada y llamará de nuevo al decodificador.
50+
51+   La función debe devolver un valor positivo si ha procesado algo, cero si no (por ejemplo, porque no hay espacio disponible en cualquiera de las memorias de entrada o de salida), y negativo en el caso de datos de entrada con secuencias ilegales. En el futuro, se intentará categorizar los errores de decodificación, pero en la actualidad cualquier valor de retorno negativo simplemente cancela la lectura con el mensaje 'Decoding error'.
52+
53+   Aún en el caso de error en los datos de entrada el decodificador debe disminuir `OutCnt` para reflejar el número de caracteres procesado con éxito. Esto será utilizado por el lector para ofrecer información de localización en el mensaje de error de excepción.
54+
55+### Ejemplo de decodificador
56+
57+   Lo que sigue es un ejemplo de una unidad que decodifica cp866. Este decodificador no tiene estado, por lo que no utiliza los miembros `Cleanup` y `Context`. Este ejemplo es muy fácil de modificar para manejar cualquier codificación similar de un solo byte con sólo reemplazar la tabla de conversión.
58+
59+``` pascal
60+ unit xmlcp866;
61+
62+ interface
63+
64+ implementation
65+
66+ uses
67+ SysUtils, xmlread;
68+
69+ const
70+ cp866table: array[#128..#255] of WideChar=(
71+ #$0410, #$0411, #$0412, #$0413, #$0414, #$0415, #$0416, #$0417,
72+ #$0418, #$0419, #$041A, #$041B, #$041C, #$041D, #$041E, #$041F,
73+ #$0420, #$0421, #$0422, #$0423, #$0424, #$0425, #$0426, #$0427,
74+ #$0428, #$0429, #$042A, #$042B, #$042C, #$042D, #$042E, #$042F,
75+ #$0430, #$0431, #$0432, #$0433, #$0434, #$0435, #$0436, #$0437,
76+ #$0438, #$0439, #$043A, #$043B, #$043C, #$043D, #$043E, #$043F,
77+ #$2591, #$2592, #$2593, #$2502, #$2524, #$2561, #$2562, #$2556,
78+ #$2555, #$2563, #$2551, #$2557, #$255D, #$255C, #$255B, #$2510,
79+ #$2514, #$2534, #$252C, #$251C, #$2500, #$253C, #$255E, #$255F,
80+ #$255A, #$2554, #$2569, #$2566, #$2560, #$2550, #$256C, #$2567,
81+ #$2568, #$2564, #$2565, #$2559, #$2558, #$2552, #$2553, #$256B,
82+ #$256A, #$2518, #$250C, #$2588, #$2584, #$258C, #$2590, #$2580,
83+ #$0440, #$0441, #$0442, #$0443, #$0444, #$0445, #$0446, #$0447,
84+ #$0448, #$0449, #$044A, #$044B, #$044C, #$044D, #$044E, #$044F,
85+ #$0401, #$0451, #$0404, #$0454, #$0407, #$0457, #$040E, #$045E,
86+ #$00B0, #$2219, #$00B7, #$221A, #$2116, #$00A4, #$25A0, #$00A0);
87+
88+ function cp866Decode(Context: Pointer; InBuf: PChar; var InCnt: Cardinal; OutBuf: PWideChar;
89+ var OutCnt: Cardinal): Integer; stdcall;
90+ var
91+ I: Integer;
92+ cnt: Cardinal;
93+ begin
94+ cnt := OutCnt; // num of widechars
95+ if cnt > InCnt then
96+ cnt := InCnt;
97+ for I := 0 to cnt-1 do
98+ begin
99+ if InBuf[I] < #128 then
100+ OutBuf[I] := WideChar(ord(InBuf[I]))
101+ else
102+ OutBuf[I] := cp866table[InBuf[I]];
103+ end;
104+ Dec(InCnt, cnt);
105+ Dec(OutCnt, cnt);
106+ Result := cnt;
107+ end;
108+
109+ function GetCP866Decoder(const AEncoding: string; out Decoder: TDecoder): Boolean; stdcall;
110+ begin
111+ // Most encodings typically have one or more alias names.
112+ if SameText(AEncoding, 'IBM866') or
113+ SameText(AEncoding, 'cp866') or
114+ SameText(AEncoding, '866') or
115+ SameText(AEncoding, 'csIBM866') then
116+ begin
117+ Decoder.Decode := @cp866Decode;
118+ Decoder.Cleanup := nil;
119+ Decoder.Context := nil;
120+ Result := True;
121+ end
122+ else
123+ Result := False;
124+ end;
125+
126+ initialization
127+ RegisterDecoder(@GetCP866Decoder);
128+ end.
129+```
130+
131+## Ver también
132+
133+- [[XML Tutorial/es]]
134+
135+---
136+*From the Free Pascal wiki, page "XML Decoders/es", as it stood on 2020-03-03 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
137+Category: Castellano
138+Category: Español

Back to history