O HotPDF gera, detecta e valida faturas eletrônicas ZUGFeRD e Factur-X a partir do Delphi e C++Builder. O AddFacturXAssociatedFile incorpora o XML da fatura EN 16931 em um contêiner PDF/A-3, o DetectFacturXInvoice reconhece uma fatura híbrida recebida e o HPDFValidateEInvoice executa as regras de negócios Schematron oficiais da EN 16931 contra o XML incorporado. Este artigo orienta sobre as três etapas e é honesto sobre onde o mecanismo de validação termina
A pressão por trás desse conjunto de recursos é regulatória, não técnica. A Alemanha e a França estão introduzindo gradualmente o faturamento eletrônico estruturado obrigatório para transações B2B domésticas, e ambos os mandatos convergem para o mesmo modelo híbrido: a fatura em PDF que seu ERP já produz deve conter uma contraparte em XML legível por máquina dentro dela. Uma aplicação Delphi de contabilidade ou ERP que emite faturas em PDF simples hoje tem um prazo limite rígido para começar a emitir Factur-X ou ZUGFeRD, e a diferença entre os dois nomes é menor do que o marketing sugere — Factur-X e ZUGFeRD são o mesmo padrão franco-alemão publicado sob dois nomes
O que torna um PDF uma fatura Factur-X válida?
Uma fatura Factur-X válida é um arquivo PDF/A-3 (ISO 19005-3) que incorpora exatamente um XML de fatura estruturado como arquivo associado, vincula-o a partir do catálogo do documento e o declara nos metadados de extensão XMP. Três camadas precisam estar alinhadas. Primeiro, o contêiner deve estar em conformidade com o PDF/A-3, o perfil de arquivamento que — diferentemente do PDF/A-1 e PDF/A-2 — permite arquivos incorporados de qualquer tipo. Segundo, o XML da fatura, nomeado como factur-x.xml para perfis padrão ou xrechnung.xml para a variante alemã XRechnung, deve ser registrado na matriz /AF do catálogo e na árvore /Names /EmbeddedFiles, com uma entrada AFRelationship que declara o que é o anexo: Alternative significa que o XML é uma representação equivalente da fatura visível, que é a semântica exigida pela maioria dos perfis. Terceiro, o esquema de extensão XMP do Factur-X deve nomear o arquivo incorporado, seu nível de conformidade e o tipo de documento, para que o sistema receptor possa classificar a fatura sem precisar analisar o XML
O próprio payload XML segue o modelo semântico EN 16931, a Norma Europeia que define o núcleo da fatura: comprador, vendedor, itens de linha, detalhamento de impostos, valor a pagar, cada um com um número de termo de negócio (BT-1 para o número da fatura, BT-5 para a moeda e assim por diante). A validação EN 16931, portanto, ocorre em duas camadas distintas. A validação do esquema XML verifica se o documento é um CII bem-formado com os nomes de elementos corretos. As regras de negócios do Schematron verificam se o conteúdo é coerente — se a regra BR-CO-15 é mantida e o total da fatura realmente corresponde à soma dos valores líquidos da linha mais o IVA, e se os termos obrigatórios estão presentes para o perfil declarado. Um arquivo pode passar na validação do esquema e ainda ser uma fatura inválida, razão pela qual a camada de regras de negócios existe
Por que o ZUGFeRD 2.5 não precisa de um novo contêiner
O ZUGFeRD 2.5 não altera nada no nível do contêiner PDF: as URNs de diretriz, o esquema XMP e o token de versão são idênticos ao ZUGFeRD 2.3 / Factur-X 1.0. Isso surpreende a maioria implementadores, por isso vale a pena citar a fonte. A especificação Factur-X 1.09 estabelece que o número da versão na URI do esquema de extensão PDF/A não está relacionado ao número da versão da especificação dos dados XML, e que a versão das instâncias da fatura Factur-X permanece 1.0 — tanto no XMP fx:Version quanto no BT-24 do factur-x.xml. O corpus de amostras oficial do ZUGFeRD 2.5 confirma isso: cada amostra incorpora factur-x.xml sob um URN de diretriz urn:factur-x.eu:1p0 com fx:Version igual a 1.0. O que o 2.5 realmente adiciona vive dentro do modelo de dados XML — novos elementos, como linhas de subfatura e identificadores de lote —, que é a camada de negócios que sua aplicação gera, não a camada de contêiner que a biblioteca PDF gerencia
Incorporando o XML da fatura a partir do Delphi
O THotPDF.AddFacturXAssociatedFile transforma uma execução normal de geração de PDF/A-3 em uma fatura Factur-X com uma chamada: ele incorpora os bytes XML como um arquivo associado, registra o factur-x.xml na matriz /AF do catálogo e na árvore /Names /EmbeddedFiles, e emite os metadados de extensão XMP Factur-X correspondentes. Você desenha a página da fatura legível por humanos com a API normal do canvas do HotPDF; o trabalho do contêiner é uma única linha entre BeginDoc e EndDoc
var
Pdf: THotPDF;
InvoiceXML, UBLXML: TBytes;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := 'invoice-2026-0042.pdf';
Pdf.PDFACompliance := '3B'; // PDF/A-3b container
Pdf.BeginDoc;
// embed the EN 16931 CII invoice XML as factur-x.xml
InvoiceXML := BuildInvoiceXML; // produced by your business layer
Pdf.AddFacturXAssociatedFile(InvoiceXML, 'EN 16931');
// optional: attach a UBL view as a supplementary representation
UBLXML := BuildUBLXML;
Pdf.AddUBLSupplementaryFile(UBLXML); // factur-xubl.xml, Alternative
// ... draw the visible invoice page here ...
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
Os padrões seguem a especificação: nome do arquivo factur-x.xml, relação Alternative, versão 1.0. O AddUBLSupplementaryFile implementa a seção 6.4 da especificação Factur-X 1.09, que permite que uma representação UBL da mesma fatura acompanhe como um segundo anexo chamado factur-xubl.xml com tipo MIME application/xml e relação Alternative. A ordem aqui importa, e o HotPDF impõe a restrição que a especificação sugere: o arquivo UBL é uma visualização complementar, nunca a fatura principal, por isso deve ser adicionado depois que o AddFacturXAssociatedFile registrou o master CII. Observe que a página desenhada e o XML incorporado devem apresentar a mesma fatura — um PDF que exibe um total e codifica outro é exatamente o modo de falha que o faturamento híbrido foi projetado para evitar. O lado do PDF/A-3 deste fluxo de trabalho, incluindo OutputIntent e incorporação de fontes, é abordado em mais detalhes no artigo complementar sobre validação de PDF/A, PDF/X e PDF/UA no Delphi
Como detectar uma fatura Factur-X em um PDF recebido?
O THotPDF.DetectFacturXInvoice atende ao lado receptor do mandato: carregue qualquer PDF e descubra em uma chamada se ele é uma fatura híbrida, qual perfil ele declara e quais anexos ele carrega. A função retorna um registro THPDFFacturXInvoiceInfo com o nome do arquivo XML incorporado, o nome e tipo de arquivo do documento declarado no XMP, o token da versão, o nível de conformidade, a URN da diretriz e o valor AFRelationship. Dois campos adicionais informam visualizações complementares: UBLFileName é preenchido quando um anexo factur-xubl.xml está presente, e EDIFACTFileName quando uma visualização EDIFACT acompanha — nenhum dos dois afeta o veredicto de detecção, pois uma representação complementar não pode existir sem a fatura CII principal
var
Reader: THotPDF;
Info: THPDFFacturXInvoiceInfo;
begin
Reader := THotPDF.Create(nil);
try
if Reader.LoadFromFile('incoming-invoice.pdf') <= 0 then
raise Exception.Create('No pages loaded.');
if Reader.DetectFacturXInvoice(Info) then
begin
Writeln('Invoice XML: ', string(Info.FileName));
Writeln('Conformance: ', string(Info.ConformanceLevel));
Writeln('Guideline URN: ', string(Info.GuidelineID));
Writeln('Relationship: ', string(Info.AFRelationship));
if Info.UBLFileName <> '' then
Writeln('UBL view: ', string(Info.UBLFileName));
end
else
Writeln('Not a Factur-X / ZUGFeRD hybrid invoice.');
finally
Reader.Free;
end;
end;
A detecção lê os mesmos sinais que um validador compatível lê — o esquema de extensão XMP e o registro de arquivo associado — em vez de adivinhar apenas pelos nomes dos arquivos. O mesmo objeto do documento carregado também expõe os metadados XMP e do dicionário Info para inspeção ou correção, um fluxo de trabalho descrito no artigo sobre edição de metadados em documentos PDF carregados
Regras de negócios ou esquema: o que significa a validação EN 16931?
O HPDFValidateEInvoice, uma função autônoma na unidade HPDFEInvoiceValidator, executa ambas as camadas de validação em sequência: primeiro a verificação da estrutura do contêiner via ValidateFacturXInvoice, depois as regras de negócios do Schematron EN 16931 contra o XML da fatura extraído. O HotPDF fornece os cinco arquivos de regras oficiais do Factur-X 1.09 — MINIMUM, BASIC WL, BASIC, EN 16931 e EXTENDED — sob Lib/resources/Schematron/, e o HPDFSchematronFileForProfile escolhe o arquivo que corresponde ao nível de conformidade detectado, de modo que uma fatura EN 16931 é verificada automaticamente contra Factur-X_1.09_EN16931.sch. A função retorna True apenas quando o contêiner é válido e nenhuma regra de negócio foi acionada
uses HPDFEInvoiceValidator;
var
Reader: THotPDF;
Report: THPDFEInvoiceValidationReport;
I: Integer;
begin
Reader := THotPDF.Create(nil);
try
Reader.LoadFromFile('incoming-invoice.pdf');
if HPDFValidateEInvoice(Reader, SchematronDir, Report) then
Writeln('Container and business rules: OK')
else
Writeln('Validation found issues.');
if Report.BusinessRulesEvaluated then
begin
Writeln(Report.BusinessSummary.Evaluated, ' rules evaluated, ',
Report.BusinessSummary.Skipped, ' skipped (XPath 2.0)');
for I := 0 to High(Report.BusinessRules) do
if (not Report.BusinessRules[I].Skipped) and
(Report.BusinessRules[I].Severity = stsError) then
Writeln(string(Report.BusinessRules[I].RuleID), ': ',
string(Report.BusinessRules[I].Message));
end;
finally
Reader.Free;
end;
end;
Cada entrada em BusinessRules carrega o identificador de regra analisado a partir do texto da asserção — BR-45, BR-CO-17 e o restante do esquema de nomenclatura da EN 16931 — além do XPath do contexto da regra, da expressão de teste e de uma severidade que reflete o atributo flag do Schematron. Isso torna o relatório acionável: em vez de um simples aprovado/reprovado, você obtém o termo comercial exato que é inconsistente, que é o que sua equipe de suporte precisa quando um cliente pergunta por que uma fatura foi rejeitada. Equipes que já geram relatórios de conformidade estruturados para PDFs de arquivamento podem integrar esses resultados no mesmo pipeline descrito no artigo sobre automação de relatórios de preflight de PDF
Onde o validador para, honestamente
O mecanismo Schematron é construído sobre o MSXML, que avalia XPath 1.0. O arquivo de regras EN 16931 declara queryBinding="xslt2" e contém 424 asserções, a maioria das quais usa apenas funções XPath 1.0, como string-length e substring-after — que rodam nativamente. Uma minoria depende de construções XPath 2.0, como conversões para xs:decimal ou exists(); o HotPDF pré-examina cada expressão de teste em busca de tokens XPath 2.0 conhecidos e marca essas regras como Skipped com severidade info em vez de tentar uma avaliação que falharia silenciosamente. O registro de resumo relata as contagens avaliadas e puladas separadamente, de modo que seu log sempre declara exatamente quanto do conjunto de regras foi exercitado. No Delphi 7, onde os vínculos do MSXML não estão disponíveis, a unidade compila um stub que relata o mecanismo como indisponível sem alterar o veredicto do contêiner; o mecanismo completo requer o Delphi XE2 ou posterior
O segundo limite importa ainda mais. Um resultado verde do HPDFValidateEInvoice significa que a estrutura do contêiner está em conformidade e nenhuma regra de negócios avaliada foi acionada — não é um endosso de conformidade fiscal. Regras de extensão nacionais, requisitos específicos do receptor e as obrigações legais em torno do conteúdo da fatura situam-se acima do núcleo da EN 16931 e fora de qualquer biblioteca. Trate o validador como o portão que mantém faturas estruturalmente corrompidas fora da sua caixa de saída e sinaliza faturas inconsistentes na sua caixa de entrada, execute um validador XPath 2.0 completo no seu pipeline de lançamento quando a certificação exigir, e deixe seus consultores fiscais assumirem a questão da conformidade. As APIs de incorporação, detecção e validação mostradas aqui fazem parte do padrão HotPDF Component para Delphi and C++Builder, com um exemplo completo de E-Invoice abrangendo todos os sete perfis ZUGFeRD e Factur-X