Parser de XML
A biblioteca parseia o XML da NFS-e Nacional (v1.01, com ou sem grupo IBS/CBS) em estruturas PHP prontas para uso. Há duas saídas equivalentes: array associativo ou DTO tipado.
Como array — XmlToArray
DanfseNacional\XmlToArray converte o XML em um array associativo limpo.
use DanfseNacional\XmlToArray;
$xml = file_get_contents('nfse_autorizada.xml');
$array = (new XmlToArray())->convert($xml);
echo $array['infNFSe']['nNFSe']; // "10"
echo $array['infNFSe']['emit']['CNPJ']; // "11222333000181"
echo $array['infNFSe']['valores']['vLiq']; // "1292.75"
Namespace NFS-e
XmlToArray conhece o namespace http://www.sped.fazenda.gov.br/nfse e extrai apenas os filhos sob esse namespace. A assinatura digital (http://www.w3.org/2000/09/xmldsig#) é descartada.
Atributos XML
Atributos sem namespace (ex.: Id, versao) são incluídos como chaves regulares do array.
Elementos repetíveis
Elementos com cardinalidade repetível no leiaute (1-N ou 0-N) são sempre materializados como array indexado, mesmo quando há uma única ocorrência. Isso mantém o mapeamento estável para list<Foo> no DTO.
Lista atual (ver XmlToArray::REPEATABLE_ELEMENTS):
xItemPedrefNFSedocAjusteBCdocDedRedbensMoveisgUnidImobgAjusteBCLocImoveis
Para qualquer nome fora dessa lista, o parser retorna a última ocorrência encontrada — comportamento compatível com a versão histórica da biblioteca.
Como objeto DTO — DanfseGenerator::parseXml()
Para uma API tipada, use DanfseGenerator::parseXml(), que retorna um objeto DanfseNacional\Dto\NFSe com propriedades readonly:
use DanfseNacional\DanfseGenerator;
$nfse = (new DanfseGenerator())->parseXml($xml);
echo $nfse->infNFSe->nNFSe; // "10"
echo $nfse->infNFSe->emit->xNome; // "EMPRESA EXEMPLO..."
echo $nfse->infNFSe->valores->vLiq; // "1292.75"
echo $nfse->infNFSe->DPS->infDPS->dCompet; // "2026-01-15"
Para XMLs com bloco IBS/CBS:
$nfse = (new DanfseGenerator())->parseXml($xmlV2);
$ibsCbs = $nfse->infNFSe->IBSCBS;
$aliqIBSUF = $ibsCbs->valores?->uf?->pAliqEfetUF;
$aliqCBS = $ibsCbs->valores?->fed?->pAliqEfetCBS;
$vTotalCBS = $ibsCbs->totCIBS?->gCBS?->vCBS;
Exemplo completo:
examples/example_parse.php.
Por dentro: como o parser funciona
DanfseGenerator::parseXml() orquestra três etapas:
XmlToArray::convert()— XML → array associativo.normalizeLegacySchema()— campos renomeados entre NT 008 e NT 009 (vDedRed→vAjusteBC::$pDR/$vDR) são mesclados no DTO único do modelo NT 009, evitando perda silenciosa de dados em NFS-e legadas (DPS versao="1.00").nullifyEmptyGroups()— strings vazias em posições de grupo nullable (?Objeto) viramnull, evitando rejeição pelo Valinor quando o XML traz<tribFed/>ou<vDescCondIncond/>vazios.
Por fim, o array é mapeado para DanfseNacional\Dto\NFSe via CuyZ/Valinor com allowSuperfluousKeys() e allowPermissiveTypes(). Chaves XML não mapeadas para uma propriedade do DTO são ignoradas (não lançam exceção), o que dá resiliência contra versões futuras do leiaute.
Robustez de campos ausentes
Todos os campos opcionais no esquema da NFS-e são representados como propriedades nullable ou com valor padrão de string vazia. O acesso a um campo ausente nunca lança exceção.
Limitação conhecida — documentos/docDedRed e documentos/docAjusteBC
Ainda não são parseados na 2.0.0: o leiaute permite 1-1000 ocorrências com choice groups internos (chNFSe, chNFe, NFSeMun, NFNFS, nDocFisc, nDoc, tpDedRed etc.) e nenhum XML real testado até o momento traz esse grupo.
Quando uma NFS-e real trouxer vDedRed/documentos ou vAjusteBC/documentos, o grupo será adicionado sem breaking change.