Boa tarde!
Gostaria de fazer uma contribuição referente a mensagem de erro que a LibXml2 retorna ao identificar uma tag com valor incorreto (maior que o permitido, menor que o permitido, etc.).
Atualmente, a mensagem está assim:
--> 1831 - Element '{http://www.portalfiscal.inf.br/nfe}xBairro': [facet 'minLength'] The value has a length of '1'; this underruns the allowed minimum length of '2'.
Dependendo da tag, ela se repete várias vezes no XML e demoramos mais para identificar onde ela realmente está na estrutura. Então quis colocar o caminho completo da estrutura do XML até chegar na tag problemática, para ficar assim:
--> 1831 - Element '{http://www.portalfiscal.inf.br/nfe}/NFe/infNFe/dest/enderDest/xBairro': [facet 'minLength'] The value has a length of '1'; this underruns the allowed minimum length of '2'.
Procurei nos fontes e não encontrei nada que ativasse esse comportamento. Por isso criei um método que devolve o caminho completo do nodo raiz até a tag.
Na ACBrLibXml2.pas, o novo método:
function xmlGetNodePathNoNS(Node: xmlNodePtr): string;
var s: String;
begin
Result := '';
while Assigned(Node) do
begin
// xmlNode.name é um PAnsiChar, converte para string Delphi
s := Trim(string(Node^.name));
if s <> '' then
Result := '/' + s + Result;
Node := Node^.parent;
end;
end;
E na ACBrDFeXsLibXml2.pas, alterei a parte que atribui a mensagem de erro ao Result na TentaPegarMensagemErroDetalhada. A ideia é substituir o "xBairrro" pelo retorno da função xmlGetNodePathNoNS.
function TDFeSSLXmlSignLibXml2.TentaPegarMensagemErroDetalhada(const MsgErroAtual: string): String;
var
prtUltimoErroXml: xmlErrorPtr;
begin
Result := '';
prtUltimoErroXml := xmlGetLastError();
if prtUltimoErroXml = nil then
begin
Result := MsgErroAtual;
Exit;
end;
Result := MsgErroAtual + ' --> ' + IntToStr(prtUltimoErroXml^.code);
if (prtUltimoErroXml^.message <> nil) then
//Result := Result + ' - ' + prtUltimoErroXml^.message; //Era assim
Result := Result + ' - ' + StringReplace(prtUltimoErroXml^.message, xmlNodePtr(prtUltimoErroXml^.node)^.name,
xmlGetNodePathNoNS(prtUltimoErroXml^.node), [rfIgnoreCase]); //Ficou assim
end;
Estou a disposição para discutir se essa seria a melhor maneira de fazer isso.