Segue um resumo das alterações que testei para restaurar o preenchimento do %TAGNIVEL% no novo XmlWriter.
Na versão antiga baseada no PCN/Gerador, o formato abaixo exibia corretamente o nível da tag:
Configuracoes.Geral.FormatoAlerta := 'TAG:%TAGNIVEL% ID:%ID%/%TAG%(%DESCRICAO%) - %MSG%.';
Com a nova geração via ACBrXmlWriter, o %TAGNIVEL% não era mais preenchido.
A solução implementada foi reconstruir o nível da tag a partir do próprio nó XML, usando a árvore já montada pela libxml2. Para isso, foram feitos estes ajustes principais:
ACBrXmlDocument.pas
Foi adicionada a propriedade TagNivel em TACBrXmlNode, montando o caminho da tag a partir dos nós parent da libxml2.
Também foi incluída a montagem dos atributos no nível da tag, preservando casos como:
<det nItem="1">
<infNFe Id="..." versao="4.00">
Exemplo de saída:
TAG:<det nItem="1"><prod><NCM> ID:I05/NCM(Código NCM) - Nenhum valor informado.
Foi adicionada também a propriedade IgnorarTagNivel no TACBrXmlDocument, permitindo ignorar tags no nível, comportamento semelhante ao antigo:
FDocument.IgnorarTagNivel := '|NFe|infNFe|obsCont|obsFisco|';
A comparação é feita pelo início da tag, permitindo ignorar corretamente:
<NFe>
<infNFe Id="..." versao="4.00">
sem depender da ordem dos atributos.
ACBrXmlWriter.pas
Foi centralizada a formatação do alerta em FormatarAlerta, voltando a substituir:
%TAGNIVEL%
%TAG%
%ID%
%MSG%
%DESCRICAO%
Também foi criado um mecanismo de alertas pendentes. A ideia é registrar o alerta com o nó XML correspondente e formatar a mensagem apenas no final da geração, quando o nó já está anexado na árvore e o TagNivel pode ser calculado corretamente.
Foi criado um overload de wAlerta:
procedure wAlerta(ANode: TACBrXmlNode; const ID, TAG, Descricao, Alerta: string; ADoException: Boolean = False); overload;
O método original continua existindo:
procedure wAlerta(const ID, TAG, Descricao, Alerta: string; ADoException: Boolean = False); overload;
Para manter compatibilidade com os pontos já existentes, o AddNode registra internamente a relação:
ID/TAG -> TACBrXmlNode
Assim, chamadas manuais já existentes como esta continuam funcionando:
Result.AppendChild(AddNode(tcStr, 'I03', 'cEAN', 00, 14, 1,
NFe.Det[i].Prod.cEAN, DSC_CEAN));
if ErroValidarGTIN <> '' then
wAlerta('I03', 'cEAN', DSC_CEAN, ErroValidarGTIN);
O wAlerta localiza o nó registrado pelo AddNode e consegue preencher o %TAGNIVEL%.
ACBrNFe.XmlWriter.pas
No construtor do TNFeXmlWriter, foi configurado o filtro de tags ignoradas:
FDocument.IgnorarTagNivel := '|NFe|infNFe|obsCont|obsFisco|';
No início da geração, foi trocado o ListaDeAlertas.Clear por LimparAlertas, para limpar também alertas pendentes e o mapa interno de nós.
No final do GerarXml, foi chamada a rotina:
FinalizarAlertasPendentes;
Isso garante que os alertas sejam formatados depois que o XML já estiver montado.
Validação com exceção opcional
Também foi adicionada a opção ExceptionValidacao, com padrão False, para preservar o comportamento atual.
Quando False, o comportamento segue como alerta normal.
Quando True, algumas validações podem lançar exceção usando o próprio alerta formatado, por exemplo em casos como CNPJ/CPF inválido, município inválido, UF inválida etc.
A configuração foi adicionada em TGeralConfNFe e repassada para o TNFeXmlWriterOptions.
Exemplo:
Configuracoes.Geral.ExceptionValidacao := True;
Com isso, é possível escolher se inconsistências de validação devem apenas entrar na lista de alertas ou interromper a geração.
Resultado dos testes
Com NCM vazio em item, o alerta passou a sair assim: TAG:<det nItem="1"><prod><NCM> ID:I05/NCM(Código NCM) - Nenhum valor informado.
Com GTIN inválido em cEAN, o alerta também passou a preencher o nível corretamente: TAG:<det nItem="1"><prod><cEAN> ID:I03/cEAN(Código de Barra do Item) - Código GTIN inválido
E com CNPJ inválido, o alerta é registrado corretamente. Se ExceptionValidacao=True, a validação pode interromper a geração lançando exceção TAG:<CNPJ> ID:E02/CNPJ(CNPJ) - Conteúdo inválido..
O objetivo foi restaurar o comportamento do %TAGNIVEL% sem alterar a estrutura do XML gerado.
ACBrDFe_tag_nivel.zip