Recentemente tive a necessidade de implementar um corretor ortográfico em uma solução Delphi.
Pedi algumas indicações e me sugeriram:
http://www.devmedia.com.br/corretor-ortografico-no-delphi/2544
http://devexpress.com/Products/VCL/ExSpellChecker/
Não cheguei a testá-los mas foram muito bem recomendados.
Mas durante minhas pesquisas acabei me deparando com uma solução do Google.
Eu não tenho certeza, e se algum leitor for mais bem informado e puder fazer a gentileza de colocar as suas considerações nos comentários, mas o Google tem um recurso chamado Google Tool Bar Proxy e um dos recursos oferecidos é justamente o de correção ortográfica.
A URL do serviço é:
http://www.google.com/tbproxy/spell?lang=pt&hl=pt
Basicamente deve-se fazer um POST (HTTP) com um conteúdo XML e analisar o retorno.
Vamos imaginar então a palavra "coracao". O XML de requisição seria:
coracao
E uma resposta válida seria algo como:
coração
Indo ao ponto, desenvolvi o código abaixo devidamente comentado. É um projeto do tipo console.
É um ótimo exemplo pois tem uma pitada de XML e Expressão Regular.
Confesso que levei algumas boas horas para desenvolver este exemplo.
Me atrapalhei com o TXMLDocument e o UTF-8. Graças a este post de Caio Oliveira consegui resolver e me dei conta de um aparente bug. Achei estranho, mas de fato foi a solução.
Neste projeto foi desenvolvido a classe TCorretor onde efetivamente esta a solução.
program CorretorOrtografico;
{$APPTYPE CONSOLE}
{$R *.res}
uses System.SysUtils,
Xml.XMLDoc,
Xml.XMLIntf,
IdHTTP,
System.Classes,
WinApi.ActiveX,
System.RegularExpressions,
IdGlobal;
type
///
/// Implementa o recurso de correção ortográfica oferecido pelo Google
///
///
/// Descende de TComponent para servir de base para o XMLDocument
///
///
/// José Mário Silva Guedes - jmarioguedes@gmail.com - eugostododelphi.blogspot.com
///
TCorretor = class(TComponent)
private
///
/// Estrutura do documento XML
///
FXML: TXMLDocument;
///
/// Comunicação HTTP
///
FHTTP: TidHTTP;
public
procedure AfterConstruction; override;
///
/// Processa efetivamente o corretor ortográfico
///
/// /// Texto de entrada
/// /// /// Possibilidades de correção
/// /// /// Motivo de um eventual insucesso
/// ///
/// Indica o sucesso da operação
///
function Processar(AEntrada: string; ASaida: TStrings; AMotivo: string): Boolean;
end;
var
bRet : Boolean;
oCorretor: TCorretor;
sEntrada : string;
slSaida : TStringList;
sMotivo : string;
sPalavra : string;
cSaida : Char;
{ TCorretor }
procedure TCorretor.AfterConstruction;
begin
inherited;
Self.FHTTP := TidHTTP.Create(Self);
Self.FXML := TXMLDocument.Create(TDataModule.Create(Self));
end;
function TCorretor.Processar(AEntrada: string; ASaida: TStrings; AMotivo: string): Boolean;
const
C_URL = 'http://www.google.com/tbproxy/spell?lang=pt&hl=pt';
var
oRequest : TStringStream;
oResponse : TStringStream;
sResponse : string;
sRequest : string;
sResultado: string;
_raiz : IXMLNode;
_texto : IXMLNode;
_resultado: IXMLNode;
aPartes : TArray;
begin
oRequest := nil;
oResponse := nil;
try
{$REGION 'Preparando o pedido'}
Self.FXML.Active := False;
Self.FXML.Active := True;
Self.FXML.Version := '1.0';
Self.FXML.Encoding := 'UTF-16';
_raiz := Self.FXML.AddChild('spellrequest');
_raiz.Attributes['textalreadyclipped'] := '0';
_raiz.Attributes['ignoredups'] := '0';
_raiz.Attributes['ignoredigits'] := '1';
_raiz.Attributes['ignoreallcaps'] := '0';
_texto := Self.FXML.CreateNode('text');
_texto.Text := AEntrada;
_raiz.ChildNodes.Add(_texto);
{$ENDREGION}
{$REGION 'Gambiarra do UTF-8'}
Self.FXML.SaveToXML(sRequest);
// http://www.caiooliveira.com.br/?p=422
// http://qc.embarcadero.com/wc/qcmain.aspx?d=37433
sRequest := TRegEx.Replace(sRequest, 'UTF-16', 'UTF-8');
oRequest := TStringStream.Create;
oRequest.WriteString(sRequest);
oRequest.Seek(0, 0);
{$ENDREGION}
{$REGION 'Request\Response'}
Self.FHTTP.Request.Accept := 'text/xml';
Self.FHTTP.Request.ContentType := 'text/xml';
Self.FHTTP.Request.ContentEncoding := 'utf-8';
oResponse := TStringStream.Create;
Self.FHTTP.Post(C_URL, oRequest, oResponse);
sResponse := UTF8ToString(RawByteString(oResponse.DataString));
Self.FXML.Active := False;
Self.FXML.LoadFromXML(sResponse);
{$ENDREGION}
{$REGION 'Analisando a resposta'}
_resultado := Self.FXML.DocumentElement.ChildNodes.FindNode('c');
while (Assigned(_resultado)) do
begin
sResultado := _resultado.Text;
aPartes := TRegEx.Split(sResultado, #9);
for sResultado in aPartes do
begin
ASaida.Add(sResultado);
end;
_resultado := _resultado.NextSibling;
end;
Result := True;
{$ENDREGION}
finally
if (Assigned(oRequest)) then
begin
oRequest.Free;
end;
if (Assigned(oResponse)) then
begin
oResponse.Free;
end;
end;
end;
begin
oCorretor := nil;
slSaida := nil;
ReportMemoryLeaksOnShutdown := True;
CoInitialize(nil);
try
Writeln('/--------------------------------------------------------------\');
Writeln('| .:: DEMONSTRAÇÃO DE USO DO CORRETOR ORTOGRÁFICO GOOGLE ::. |');
Writeln('| jmarioguedes@gmail.com - http://eugostododelphi.blogspot.com |');
Writeln('\--------------------------------------------------------------/');
Writeln('');
Writeln('');
oCorretor := TCorretor.Create(nil);
slSaida := TStringList.Create;
repeat
write('Digite um texto: ');
Readln(sEntrada);
Writeln('');
slSaida.Clear;
bRet := oCorretor.Processar(sEntrada, slSaida, sMotivo);
if (bRet) then
begin
if (slSaida.Count > 0) then
begin
for sPalavra in slSaida do
begin
Writeln('-> ' + sPalavra);
end;
Writeln('');
end
else
begin
Writeln('Não houve resultados');
end;
end
else
begin
Writeln(Format('Insucesso na correção: ', [sMotivo]));
end;
Write('Tecle X para cancelar ou qualquer outra tecla para continuar: ');
ReadLn(cSaida);
until (CharInSet(cSaida, ['X', 'x']));
finally
if (Assigned(oCorretor)) then
begin
oCorretor.Free;
end;
if (Assigned(slSaida)) then
begin
slSaida.Free;
end;
Writeln('- Fim do Sistema - ');
Readln;
end;
end.