Difference between revisions of "XML Decoders/es"

From Lazarus wiki
Jump to navigationJump to search
(New page: {{XML Decoders}} Category:CastellanoCategory:Español == XML Decodificadores ==    A partir de la revisión de SVN 12582, el lector de XML es capaz de proc...)
 
m (Fixed syntax highlighting)
 
(4 intermediate revisions by 2 users not shown)
Line 18: Line 18:
 
==== GetDecoder ====
 
==== GetDecoder ====
  
<delphi>function GetDecoder(const AEncoding: string; out Decoder: TDecoder): Boolean; stdcall;</delphi>
+
<syntaxhighlight lang=pascal>function GetDecoder(const AEncoding: string; out Decoder: TDecoder): Boolean; stdcall;</syntaxhighlight>
  
 
&nbsp;&nbsp;&nbsp;En el momento de la iniciación del programa, el decodificador se registra llamando al procedimiemto <code> XMLRead.RegisterDecoder</code> y pasando la función <code> GetDecoder </code> como argumento.
 
&nbsp;&nbsp;&nbsp;En el momento de la iniciación del programa, el decodificador se registra llamando al procedimiemto <code> XMLRead.RegisterDecoder</code> y pasando la función <code> GetDecoder </code> como argumento.
Line 26: Line 26:
 
==== Cleanup ====
 
==== Cleanup ====
  
<delphi>procedure Cleanup(Context: Pointer); stdcall;</delphi>
+
<syntaxhighlight lang=pascal> procedure Cleanup(Context: Pointer); stdcall;</syntaxhighlight>
  
If <code>GetDecoder</code> sets the <code>Decoder.Cleanup</code> member, it is called by reader once, after processing of the current entity is finished. As the name suggests, the decoder should then free all resources it allocated.
+
&nbsp;&nbsp;&nbsp;Si <code>GetDecoder</code> establece el miembro <code>Decoder.Cleanup</code>, 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.
  
The value of <code>Decoder.Context</code> is passed to <code>Decode</code> and <code>Cleanup</code> procedures each time they are called. The reader does not assign any meaning to this value.
+
&nbsp;&nbsp;&nbsp;El valor de <code>Decoder.Context</code> se pasa a los procedimientos <code>Decode</code> y <code>Cleanup</code> cada vez que es llamado. El lector no da ningún significado a este valor.
  
 
==== Decode ====
 
==== Decode ====
  
<delphi>function Decode(Context: Pointer; InBuf: PChar; var InCnt: Cardinal;
+
<syntaxhighlight lang=pascal> function Decode(Context: Pointer; InBuf: PChar; var InCnt: Cardinal; OutBuf: PWideChar; var OutCnt: Cardinal): Integer; stdcall;</syntaxhighlight>
  OutBuf: PWideChar; var OutCnt: Cardinal): Integer; stdcall;</delphi>
 
  
The <code>Decode</code> function does the main job. It should convert the input data pointed by <code>InBuf</code> into UTF-16 in the current platform endianness and place it into <code>OutBuf</code>. The size of input buffer is supplied in
+
&nbsp;&nbsp;&nbsp;La función <code>Decode</code> hace el trabajo principal. Convierte los datos de entrada apuntados por <code>inbuf</code> a UTF-16 formato de boble byte de la plataforma actual y la pone en <code>outbuf</code>. El tamaño del espacio de entrada se muestra en
<code>InCnt</code>, the space avaliable in output buffer is in <code>OutCnt</code>.
+
<code>InCnt</code>, el espacio disponible en el espacio de salida se encuentra en <code>OutCnt</code>.  
  
The important difference to note is that <code>InCnt</code> is given in '''bytes''', while <code>OutCnt</code> is in '''WideChars'''.
+
&nbsp;&nbsp;&nbsp;Una diferencia importante a destacar es que <code>InCnt</code> se da en '''bytes''', mientras que <code>OutCnt</code> está en '''WideChars'''.
  
The function must decrement <code>InCnt</code> and <code>OutCnt</code> according to the amount of data it processes. Each processed character decrements <code>OutCnt</code> by one (or by two in case the surrogate pair is written); the amount of <code>InCnt</code> decrement depends on the actual encoding.
+
&nbsp;&nbsp;&nbsp;La función debe decrementar <code>InCnt</code> y <code>OutCnt</code> de acuerdo a la cantidad de datos procesados. Cada carácter procesados disminuye <code>OutCnt</code> en una unidad (o dos en caso de que el sustituto escrito sea doble), la cantidad a disminuir de <code>InCnt</code> depende de la codificación real.
  
No assumptions should be made about initial size of buffers: for example, the reader may call decoder with only a few bytes in input buffer. The decoder function then should return zero indicating nothing is processed, and the reader will fetch more input and call decoder again.
+
&nbsp;&nbsp;&nbsp;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.
  
The function should return positive value if it had processed something, zero if it had not (e.g. because no space available in either input or output buffer), and negative value in cause the input data contains illegal sequence. In the future, there may be attempt to categorize the decoding errors, but currently any negative return simply aborts the reader with the 'Decoding error' message.
+
&nbsp;&nbsp;&nbsp;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'.
  
In case of error in input data the decoder should still decrement <code>OutCnt</code> to reflect the number of successfully processed characters. This will be used by reader to provide location information in the exception error message.
+
&nbsp;&nbsp;&nbsp;Aún en el caso de error en los datos de entrada el decodificador debe disminuir <code>OutCnt</code> 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.
  
=== Sample decoder ===
+
=== Ejemplo de decodificador ===
  
Following is a sample unit that decodes cp866. This decoder is stateless, so it does not use the <code>Cleanup</code> and <code>Context</code> members. It should be very easy to modify this sample to handle any similar single-byte encoding by just replacing the conversion table.  
+
&nbsp;&nbsp;&nbsp;Lo que sigue es un ejemplo de una unidad que decodifica cp866. Este decodificador no tiene estado, por lo que no utiliza los miembros <code>Cleanup</code> y <code>Context</code>. 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.
  
<delphi>unit xmlcp866;
+
<syntaxhighlight lang=pascal> unit xmlcp866;
  
interface
+
interface
  
implementation
+
implementation
  
uses
+
uses
 
   SysUtils, xmlread;
 
   SysUtils, xmlread;
  
const
+
const
 
   cp866table: array[#128..#255] of WideChar=(
 
   cp866table: array[#128..#255] of WideChar=(
 
       #$0410, #$0411, #$0412, #$0413, #$0414, #$0415, #$0416, #$0417,
 
       #$0410, #$0411, #$0412, #$0413, #$0414, #$0415, #$0416, #$0417,
Line 82: Line 81:
 
       #$00B0, #$2219, #$00B7, #$221A, #$2116, #$00A4, #$25A0, #$00A0);
 
       #$00B0, #$2219, #$00B7, #$221A, #$2116, #$00A4, #$25A0, #$00A0);
  
function cp866Decode(Context: Pointer; InBuf: PChar; var InCnt: Cardinal; OutBuf: PWideChar;
+
function cp866Decode(Context: Pointer; InBuf: PChar; var InCnt: Cardinal; OutBuf: PWideChar;
 
                     var OutCnt: Cardinal): Integer; stdcall;
 
                     var OutCnt: Cardinal): Integer; stdcall;
var
+
var
 
   I: Integer;
 
   I: Integer;
 
   cnt: Cardinal;
 
   cnt: Cardinal;
begin
+
begin
 
   cnt := OutCnt;        // num of widechars
 
   cnt := OutCnt;        // num of widechars
 
   if cnt > InCnt then
 
   if cnt > InCnt then
Line 101: Line 100:
 
   Dec(OutCnt, cnt);
 
   Dec(OutCnt, cnt);
 
   Result := cnt;
 
   Result := cnt;
end;
+
end;
  
function GetCP866Decoder(const AEncoding: string; out Decoder: TDecoder): Boolean; stdcall;
+
function GetCP866Decoder(const AEncoding: string; out Decoder: TDecoder): Boolean; stdcall;
begin
+
begin
// Most encodings typically have one or more alias names.
+
// Most encodings typically have one or more alias names.
 
   if SameText(AEncoding, 'IBM866') or
 
   if SameText(AEncoding, 'IBM866') or
 
     SameText(AEncoding, 'cp866') or
 
     SameText(AEncoding, 'cp866') or
Line 118: Line 117:
 
   else
 
   else
 
     Result := False;
 
     Result := False;
end;
+
end;
  
initialization
+
initialization
 
   RegisterDecoder(@GetCP866Decoder);
 
   RegisterDecoder(@GetCP866Decoder);
end.</delphi>
+
end.</syntaxhighlight>
  
 
==Ver también==
 
==Ver también==
  
 
* [[XML Tutorial/es]]
 
* [[XML Tutorial/es]]

Latest revision as of 09:04, 3 March 2020

English (en) español (es) русский (ru) 中文(中国大陆)‎ (zh_CN)

XML Decodificadores

   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.

Decodificadores disponibles

   En la actualidad, un decodificador que utiliza libiconv está disponible. Tiene dos implementaciones distintas. La primera, en la unidadxmliconv.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.

Estructura del decodificador

   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:

  1. GetDecoder
  2. Decode
  3. Cleanup (optional)

   Aquí una breve descripción del funcionamiento con un decodificador externo:

GetDecoder

function GetDecoder(const AEncoding: string; out Decoder: TDecoder): Boolean; stdcall;

   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.

Cleanup

 procedure Cleanup(Context: Pointer); stdcall;

   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.

   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.

Decode

 function Decode(Context: Pointer; InBuf: PChar; var InCnt: Cardinal; OutBuf: PWideChar; var OutCnt: Cardinal): Integer; stdcall;

   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.

   Una diferencia importante a destacar es que InCnt se da en bytes, mientras que OutCnt está en WideChars.

   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.

   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.

   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'.

   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.

Ejemplo de decodificador

   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.

 unit xmlcp866;

 interface

 implementation

 uses
  SysUtils, xmlread;

 const
  cp866table: array[#128..#255] of WideChar=(
      #$0410, #$0411, #$0412, #$0413, #$0414, #$0415, #$0416, #$0417,
      #$0418, #$0419, #$041A, #$041B, #$041C, #$041D, #$041E, #$041F,
      #$0420, #$0421, #$0422, #$0423, #$0424, #$0425, #$0426, #$0427,
      #$0428, #$0429, #$042A, #$042B, #$042C, #$042D, #$042E, #$042F,
      #$0430, #$0431, #$0432, #$0433, #$0434, #$0435, #$0436, #$0437,
      #$0438, #$0439, #$043A, #$043B, #$043C, #$043D, #$043E, #$043F,
      #$2591, #$2592, #$2593, #$2502, #$2524, #$2561, #$2562, #$2556,
      #$2555, #$2563, #$2551, #$2557, #$255D, #$255C, #$255B, #$2510,
      #$2514, #$2534, #$252C, #$251C, #$2500, #$253C, #$255E, #$255F,
      #$255A, #$2554, #$2569, #$2566, #$2560, #$2550, #$256C, #$2567,
      #$2568, #$2564, #$2565, #$2559, #$2558, #$2552, #$2553, #$256B,
      #$256A, #$2518, #$250C, #$2588, #$2584, #$258C, #$2590, #$2580,
      #$0440, #$0441, #$0442, #$0443, #$0444, #$0445, #$0446, #$0447,
      #$0448, #$0449, #$044A, #$044B, #$044C, #$044D, #$044E, #$044F,
      #$0401, #$0451, #$0404, #$0454, #$0407, #$0457, #$040E, #$045E,
      #$00B0, #$2219, #$00B7, #$221A, #$2116, #$00A4, #$25A0, #$00A0);

 function cp866Decode(Context: Pointer; InBuf: PChar; var InCnt: Cardinal; OutBuf: PWideChar;
                     var OutCnt: Cardinal): Integer; stdcall;
 var
  I: Integer;
  cnt: Cardinal;
 begin
  cnt := OutCnt;         // num of widechars
  if cnt > InCnt then
    cnt := InCnt;
  for I := 0 to cnt-1 do
  begin
    if InBuf[I] < #128 then
      OutBuf[I] := WideChar(ord(InBuf[I]))
    else
      OutBuf[I] := cp866table[InBuf[I]];
  end;
  Dec(InCnt, cnt);
  Dec(OutCnt, cnt);
  Result := cnt;
 end;

 function GetCP866Decoder(const AEncoding: string; out Decoder: TDecoder): Boolean; stdcall;
 begin
 // Most encodings typically have one or more alias names.
  if SameText(AEncoding, 'IBM866') or
     SameText(AEncoding, 'cp866') or
     SameText(AEncoding, '866') or
     SameText(AEncoding, 'csIBM866') then
  begin
    Decoder.Decode := @cp866Decode;
    Decoder.Cleanup := nil;
    Decoder.Context := nil;
    Result := True;
  end
  else
    Result := False;
 end;

 initialization
  RegisterDecoder(@GetCP866Decoder);
 end.

Ver también