Implementation
Map<String, dynamic> buildInvoiceMapFromXml(XmlDocument xml) {
// Define namespaces used in the document
final namespaces = {
'cbc': 'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2',
'cac': 'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2',
'sts': 'dian:gov:co:facturaelectronica:Structures-2-1',
'ext': 'urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2',
};
// Helper function to get elements with namespace
XmlElement? getElementNS(XmlElement? parent, String namespace, String name) {
if (parent == null) return null;
return parent.findElements(name, namespace: namespaces[namespace]).firstOrNull;
}
// Helper function to get text content with namespace
String getTextNS(XmlElement? parent, String namespace, String name) {
final element = getElementNS(parent, namespace, name);
return element?.innerText ?? '';
}
try {
final invoiceElement = xml.rootElement;
// Basic invoice information
final invoiceId = getTextNS(invoiceElement, 'cbc', 'ID');
final issueDate = getTextNS(invoiceElement, 'cbc', 'IssueDate');
final issueTime = getTextNS(invoiceElement, 'cbc', 'IssueTime');
final invoiceTypeCode = getTextNS(invoiceElement, 'cbc', 'InvoiceTypeCode');
final documentCurrency = getTextNS(invoiceElement, 'cbc', 'DocumentCurrencyCode');
final uuid = getTextNS(invoiceElement, 'cbc', 'UUID');
// QR Code information
final extensionsElement = getElementNS(invoiceElement, 'ext', 'UBLExtensions');
final extensionElement = getElementNS(extensionsElement, 'ext', 'UBLExtension');
final extensionContent = getElementNS(extensionElement, 'ext', 'ExtensionContent');
final dianExtensions = extensionContent?.findElements('DianExtensions', namespace: namespaces['sts']).firstOrNull;
final qrCode = dianExtensions?.findElements('QRCode', namespace: namespaces['sts']).firstOrNull?.innerText ?? '';
// Supplier information
final supplierParty = getElementNS(invoiceElement, 'cac', 'AccountingSupplierParty');
final supplierPartyElement = getElementNS(supplierParty, 'cac', 'Party');
final supplierLegalEntity = getElementNS(supplierPartyElement, 'cac', 'PartyLegalEntity');
final supplierName = getTextNS(supplierLegalEntity, 'cbc', 'RegistrationName');
final supplierID = getTextNS(
getElementNS(supplierPartyElement, 'cac', 'PartyIdentification'),
'cbc',
'ID'
);
// Supplier contact information
final supplierContact = getElementNS(supplierPartyElement, 'cac', 'Contact');
final supplierPhone = getTextNS(supplierContact, 'cbc', 'Telephone');
final supplierEmail = getTextNS(supplierContact, 'cbc', 'ElectronicMail');
// Supplier address
final supplierLocation = getElementNS(supplierPartyElement, 'cac', 'PhysicalLocation');
final supplierAddress = getElementNS(supplierLocation, 'cac', 'Address');
final supplierAddressLine = getTextNS(
getElementNS(supplierAddress, 'cac', 'AddressLine'),
'cbc',
'Line'
);
final supplierCity = getTextNS(supplierAddress, 'cbc', 'CityName');
final supplierState = getTextNS(supplierAddress, 'cbc', 'CountrySubentity');
// Customer information
final customerParty = getElementNS(invoiceElement, 'cac', 'AccountingCustomerParty');
final customerPartyElement = getElementNS(customerParty, 'cac', 'Party');
final customerLegalEntity = getElementNS(customerPartyElement, 'cac', 'PartyLegalEntity');
final customerName = getTextNS(customerLegalEntity, 'cbc', 'RegistrationName');
final customerID = getTextNS(
getElementNS(customerPartyElement, 'cac', 'PartyIdentification'),
'cbc',
'ID'
);
// Payment information
final paymentMeans = getElementNS(invoiceElement, 'cac', 'PaymentMeans');
final paymentMeansCode = getTextNS(paymentMeans, 'cbc', 'PaymentMeansCode');
final paymentDueDate = getTextNS(paymentMeans, 'cbc', 'PaymentDueDate');
// Tax information
final taxTotal = getElementNS(invoiceElement, 'cac', 'TaxTotal');
final taxAmount = getTextNS(taxTotal, 'cbc', 'TaxAmount');
// Monetary totals
final legalMonetaryTotal = getElementNS(invoiceElement, 'cac', 'LegalMonetaryTotal');
final lineExtensionAmount = getTextNS(legalMonetaryTotal, 'cbc', 'LineExtensionAmount');
final taxExclusiveAmount = getTextNS(legalMonetaryTotal, 'cbc', 'TaxExclusiveAmount');
final taxInclusiveAmount = getTextNS(legalMonetaryTotal, 'cbc', 'TaxInclusiveAmount');
final payableAmount = getTextNS(legalMonetaryTotal, 'cbc', 'PayableAmount');
// Invoice lines (items)
final invoiceLines = invoiceElement.findElements('InvoiceLine', namespace: namespaces['cac']).map((lineElement) {
final lineId = getTextNS(lineElement, 'cbc', 'ID');
final quantity = getTextNS(lineElement, 'cbc', 'InvoicedQuantity');
final lineExtensionAmount = getTextNS(lineElement, 'cbc', 'LineExtensionAmount');
final itemElement = getElementNS(lineElement, 'cac', 'Item');
final description = getTextNS(itemElement, 'cbc', 'Description');
final priceElement = getElementNS(lineElement, 'cac', 'Price');
final priceAmount = getTextNS(priceElement, 'cbc', 'PriceAmount');
return {
'code': lineId,
'quantity': int.tryParse(quantity) ?? 0,
'lineExtensionAmount': double.tryParse(lineExtensionAmount) ?? 0,
'description': description,
'price': double.tryParse(priceAmount) ?? 0,
};
}).toList();
// Build the complete invoice map
return {
'id': invoiceId,
//'invoiceInfo': {
'uuid': uuid,
'issueDate': issueDate,
'issueTime': issueTime,
//'documentTypeId': invoiceTypeCode,
'documentCurrency': documentCurrency,
// },
'qrCode': qrCode,
'supplier': {
'id': supplierID,
'name': supplierName,
'contact': {
'phone': supplierPhone,
'email': supplierEmail,
},
'address': {
'line': supplierAddressLine,
'city': supplierCity,
'state': supplierState,
},
},
'customer': {
'identificationNumber': customerID,
'name': customerName,
},
'paymentForm': {
'meansCode': paymentMeansCode,
'dueDate': paymentDueDate,
},
'taxes': [
{
'amount': double.tryParse(taxAmount) ?? 0,
}
],
'totals': {
'lineExtensionAmount': double.tryParse(lineExtensionAmount) ?? 0,
'taxExclusiveAmount': double.tryParse(taxExclusiveAmount) ?? 0,
'taxInclusiveAmount': double.tryParse(taxInclusiveAmount) ?? 0,
'payableAmount': double.tryParse(payableAmount) ?? 0,
},
'items': invoiceLines,
};
} catch (e) {
developer.log('Error parsing XML: $e');
return {
'error': e.toString(),
};
}
}