Olá pessoal,
Eu realizei o download de um XML do SAT,/CF-e no site da receita, ao vincular esse documento no meu sistema percebi que o numero da versão não estava correto.
O problema acontece pelo seguinte motivo, antes os XML's vinham com os atributos da tag nessa ordem versao, versaoSB, versaoDadosEnt, Id, exemplo:
<infCFe versao="0.07" versaoSB="010200" versaoDadosEnt="0.07" Id="CFe00000000000000000000000000000000000000000000">
Já esse ultimo documento que fiz o download, veio com essa estrutura diferente, na ordem versaoSB, versaoDadosEnt, versao, Id, exemplo:
<infCFe versaoSB="010200" versaoDadosEnt="0.07" versao="0.07" Id="CFe00000000000000000000000000000000000000000000">
Percebi que no método rAtributo da unit pcnLeitor,.pas é feito um pos nessa linha procurando pela palavra 'versao', para o primeiro exemplo mostrado funciona, mas para o segundo exemplo não funciona. (Ao invés de retornar o número "0.07" está retornando "010200").
Para corrigir esse problema realizei algumas alterações.
Aqui está o método original sem alterações:
function TLeitor.rAtributo(Atributo: string; Tag: String): variant;
var
ConteudoTag ,
Aspas : String;
inicio ,
inicioTag ,
fim ,
iPos1 ,
iPos2 : Integer;
begin
Result := '';
Atributo := Trim(Atributo);
Tag := Trim(Tag);
inicioTag := pos(Tag, FGrupo);
inicio := pos(Atributo, FGrupo);
// se inicioTag > 0 significa que o parâmetro Tag foi informado.
// se inicioTag > inicio significa que o atributo encontrado não é da Tag informada
// logo devemos bustar a proxima ocorrecia a partir da posição da Tag.
if (inicioTag > 0) and (inicioTag > inicio) then
inicio := PosEx(Atributo, FGrupo, inicioTag);
if inicio > 0 then
begin
inicio := inicio + Length(Atributo);
ConteudoTag := trim(copy(FGrupo, inicio, maxInt));
iPos1 := Pos('"' , ConteudoTag);
iPos2 := Pos('''', ConteudoTag);
if iPos1 <> 0 then
Aspas := '"';
if (iPos2 <> 0) and ((iPos1 = 0) or (iPos2 < iPos1)) then
Aspas := '''';
inicio := pos(Aspas, ConteudoTag) + 1;
if inicio > 0 then
begin
ConteudoTag := trim(copy(ConteudoTag, inicio, maxInt));
fim := pos(Aspas, ConteudoTag) - 1;
if fim > 0 then
begin
ConteudoTag := copy(ConteudoTag, 1, fim);
result := ReverterFiltroTextoXML(ConteudoTag)
end
end ;
end ;
end;
E esse é o método com as alterações que eu fiz:
function TLeitor.rAtributo(Atributo: string; Tag: String): variant;
var
ConteudoTag ,
Aspas : String;
i ,
inicio ,
inicioTag ,
fim ,
iPos1 ,
iPos2 : Integer;
const
CharValiidacao: Array[0 .. 1] of String = (' ', '=');
begin
Result := '';
Atributo := Trim(Atributo);
Tag := Trim(Tag);
inicioTag := pos(Tag, FGrupo);
for i := 0 to High(CharValiidacao) do
begin
inicio := pos(Atributo+CharValiidacao[i], FGrupo);
if(inicio > 0)then
Break;
end;
if(inicio = 0)then
inicio := pos(Atributo, FGrupo);
// se inicioTag > 0 significa que o parâmetro Tag foi informado.
// se inicioTag > inicio significa que o atributo encontrado não é da Tag informada
// logo devemos bustar a proxima ocorrecia a partir da posição da Tag.
if (inicioTag > 0) and (inicioTag > inicio) then
inicio := PosEx(Atributo, FGrupo, inicioTag);
if inicio > 0 then
begin
inicio := inicio + Length(Atributo);
ConteudoTag := trim(copy(FGrupo, inicio, maxInt));
iPos1 := Pos('"' , ConteudoTag);
iPos2 := Pos('''', ConteudoTag);
if iPos1 <> 0 then
Aspas := '"';
if (iPos2 <> 0) and ((iPos1 = 0) or (iPos2 < iPos1)) then
Aspas := '''';
inicio := pos(Aspas, ConteudoTag) + 1;
if inicio > 0 then
begin
ConteudoTag := trim(copy(ConteudoTag, inicio, maxInt));
fim := pos(Aspas, ConteudoTag) - 1;
if fim > 0 then
begin
ConteudoTag := copy(ConteudoTag, 1, fim);
result := ReverterFiltroTextoXML(ConteudoTag)
end
end ;
end ;
end;
Não sei se essa é a melhor forma de corrigir tratar essa situação descrita.