Skip to content

Instantly share code, notes, and snippets.

@bzamecnik
Last active April 27, 2023 06:50
Show Gist options
  • Save bzamecnik/cf0c0c76d0d5cbd4d5d9d67e7ff15b23 to your computer and use it in GitHub Desktop.
Save bzamecnik/cf0c0c76d0d5cbd4d5d9d67e7ff15b23 to your computer and use it in GitHub Desktop.
Joins multiple single-file invoices in the StormWare Pohoda XML format to a single XML file.
"""
Joins multiple single-file invoices in the StormWare Pohoda XML format to a
single XML file.
https://www.stormware.cz/xml/schema/version_2/invoice.xsd
https://www.stormware.cz/schema/version_2/data.xsd
Usage:
$ python join_invoices.py 'single_invoices/*.xml' merged_invoice.xml
File encoding: windows-1250, CRLF.
"""
import argparse
import glob
from tqdm import tqdm
import xmltodict
def merge_invoices(input_path, output_path):
merged_doc = None
for path in tqdm(glob.glob(input_path)):
# use the first document as the template for the top-level structure
if merged_doc is None:
merged_doc = load_root_doc(path)
doc = load_xml(path)
item = extract_item_with_id(doc)
merged_doc['dat:dataPack']['dat:dataPackItem'].append(item)
save_xml(merged_doc, output_path)
def load_root_doc(path):
root_doc = load_xml(path)
del root_doc['dat:dataPack']['dat:dataPackItem']
# envelope id must not be empty, so let's leave there some dummy value
root_doc['dat:dataPack']['@id'] = "00001"
root_doc['dat:dataPack']['dat:dataPackItem'] = []
return root_doc
def extract_item_with_id(doc):
item = doc['dat:dataPack']['dat:dataPackItem']
item['@id'] = doc['dat:dataPack']['@id']
return item
def load_xml(path):
with open(path, 'rb') as f:
return xmltodict.parse(f)
def save_xml(doc, path):
with open(path, 'wb') as f:
xmltodict.unparse(doc, output=f, pretty=True, encoding='Windows-1250', newl='\r\n')
def parse_args():
parser = argparse.ArgumentParser(description='Join multiple Pohoda invoices')
parser.add_argument('input_path', metavar='INPUT_PATH')
parser.add_argument('output_path', metavar='OUTPUT_PATH')
return parser.parse_args()
if __name__ == '__main__':
args = parse_args()
merge_invoices(args.input_path, args.output_path)
<?xml version="1.0" encoding="Windows-1250"?>
<dat:dataPack xmlns:dat="http://www.stormware.cz/schema/version_2/data.xsd" xmlns:inv="http://www.stormware.cz/schema/version_2/invoice.xsd" xmlns:typ="http://www.stormware.cz/schema/version_2/type.xsd" application="" ico="12345678" version="2.0" note="Import FA">
<dat:dataPackItem id="F201600001" version="2.0">
<inv:invoice version="2.0">
<inv:invoiceHeader>
<inv:invoiceType>issuedInvoice</inv:invoiceType>
<inv:number>
<typ:ids></typ:ids>
<typ:numberRequested>2016000001</typ:numberRequested>
</inv:number>
<inv:symVar>2016000001</inv:symVar>
<inv:date>2016-01-01</inv:date>
<inv:dateTax>2016-01-01</inv:dateTax>
<inv:dateDue>2016-01-11</inv:dateDue>
<inv:accounting>
<typ:ids>000/000000</typ:ids>
</inv:accounting>
<inv:classificationVAT>
<typ:classificationVATType>inland</typ:classificationVATType>
</inv:classificationVAT>
<inv:text>Faktury vydan�</inv:text>
<inv:partnerIdentity>
<typ:address>
<typ:company>John Doe</typ:company>
<typ:division></typ:division>
<typ:city></typ:city>
<typ:street></typ:street>
<typ:zip></typ:zip>
<typ:ico></typ:ico>
<typ:dic></typ:dic>
</typ:address>
</inv:partnerIdentity>
<inv:paymentType>
<typ:paymentType>draft</typ:paymentType>
</inv:paymentType>
<inv:note>Na�teno z XML</inv:note>
</inv:invoiceHeader>
<inv:invoiceSummary>
<inv:homeCurrency>
<typ:priceNone>1000</typ:priceNone>
<typ:priceLow>0</typ:priceLow>
<typ:priceLowVAT>0</typ:priceLowVAT>
<typ:priceHigh>0</typ:priceHigh>
<typ:priceHighVAT>0</typ:priceHighVAT>
</inv:homeCurrency>
</inv:invoiceSummary>
</inv:invoice>
</dat:dataPackItem>
<dat:dataPackItem id="F201600002" version="2.0">
<inv:invoice version="2.0">
<inv:invoiceHeader>
<inv:invoiceType>issuedInvoice</inv:invoiceType>
<inv:number>
<typ:ids></typ:ids>
<typ:numberRequested>2016000002</typ:numberRequested>
</inv:number>
<inv:symVar>2016000002</inv:symVar>
<inv:date>2016-01-02</inv:date>
<inv:dateTax>2016-01-02</inv:dateTax>
<inv:dateDue>2016-01-12</inv:dateDue>
<inv:accounting>
<typ:ids>000/000000</typ:ids>
</inv:accounting>
<inv:classificationVAT>
<typ:classificationVATType>inland</typ:classificationVATType>
</inv:classificationVAT>
<inv:text>Faktury vydan�</inv:text>
<inv:partnerIdentity>
<typ:address>
<typ:company>Jane Dee</typ:company>
<typ:division></typ:division>
<typ:city></typ:city>
<typ:street></typ:street>
<typ:zip></typ:zip>
<typ:ico></typ:ico>
<typ:dic></typ:dic>
</typ:address>
</inv:partnerIdentity>
<inv:paymentType>
<typ:paymentType>draft</typ:paymentType>
</inv:paymentType>
<inv:note>Na�teno z XML</inv:note>
</inv:invoiceHeader>
<inv:invoiceSummary>
<inv:homeCurrency>
<typ:priceNone>500</typ:priceNone>
<typ:priceLow>0</typ:priceLow>
<typ:priceLowVAT>0</typ:priceLowVAT>
<typ:priceHigh>0</typ:priceHigh>
<typ:priceHighVAT>0</typ:priceHighVAT>
</inv:homeCurrency>
</inv:invoiceSummary>
</inv:invoice>
</dat:dataPackItem>
</dat:dataPack>
<?xml version="1.0" encoding="Windows-1250"?>
<dat:dataPack xmlns:dat="http://www.stormware.cz/schema/version_2/data.xsd" xmlns:inv="http://www.stormware.cz/schema/version_2/invoice.xsd" xmlns:typ="http://www.stormware.cz/schema/version_2/type.xsd" id="F201600001" application="" ico="12345678" version="2.0" note="Import FA">
<dat:dataPackItem id="001" version="2.0">
<inv:invoice version="2.0">
<inv:invoiceHeader>
<inv:invoiceType>issuedInvoice</inv:invoiceType>
<inv:number>
<typ:ids></typ:ids>
<typ:numberRequested>2016000001</typ:numberRequested>
</inv:number>
<inv:symVar>2016000001</inv:symVar>
<inv:date>2016-01-01</inv:date>
<inv:dateTax>2016-01-01</inv:dateTax>
<inv:dateDue>2016-01-11</inv:dateDue>
<inv:accounting>
<typ:ids>000/000000</typ:ids>
</inv:accounting>
<inv:classificationVAT>
<typ:classificationVATType>inland</typ:classificationVATType>
</inv:classificationVAT>
<inv:text>Faktury vydan�</inv:text>
<inv:partnerIdentity>
<typ:address>
<typ:company>John Doe</typ:company>
<typ:division></typ:division>
<typ:city></typ:city>
<typ:street></typ:street>
<typ:zip></typ:zip>
<typ:ico></typ:ico>
<typ:dic></typ:dic>
</typ:address>
</inv:partnerIdentity>
<inv:paymentType>
<typ:paymentType>draft</typ:paymentType>
</inv:paymentType>
<inv:note>Na�teno z XML</inv:note>
</inv:invoiceHeader>
<inv:invoiceSummary>
<inv:homeCurrency>
<typ:priceNone>1000</typ:priceNone>
<typ:priceLow>0</typ:priceLow>
<typ:priceLowVAT>0</typ:priceLowVAT>
<typ:priceHigh>0</typ:priceHigh>
<typ:priceHighVAT>0</typ:priceHighVAT>
</inv:homeCurrency>
</inv:invoiceSummary>
</inv:invoice>
</dat:dataPackItem>
</dat:dataPack>
<?xml version="1.0" encoding="Windows-1250"?>
<dat:dataPack xmlns:dat="http://www.stormware.cz/schema/version_2/data.xsd" xmlns:inv="http://www.stormware.cz/schema/version_2/invoice.xsd" xmlns:typ="http://www.stormware.cz/schema/version_2/type.xsd" id="F201600002" application="" ico="12345678" version="2.0" note="Import FA">
<dat:dataPackItem id="001" version="2.0">
<inv:invoice version="2.0">
<inv:invoiceHeader>
<inv:invoiceType>issuedInvoice</inv:invoiceType>
<inv:number>
<typ:ids></typ:ids>
<typ:numberRequested>2016000002</typ:numberRequested>
</inv:number>
<inv:symVar>2016000002</inv:symVar>
<inv:date>2016-01-02</inv:date>
<inv:dateTax>2016-01-02</inv:dateTax>
<inv:dateDue>2016-01-12</inv:dateDue>
<inv:accounting>
<typ:ids>000/000000</typ:ids>
</inv:accounting>
<inv:classificationVAT>
<typ:classificationVATType>inland</typ:classificationVATType>
</inv:classificationVAT>
<inv:text>Faktury vydan�</inv:text>
<inv:partnerIdentity>
<typ:address>
<typ:company>Jane Dee</typ:company>
<typ:division></typ:division>
<typ:city></typ:city>
<typ:street></typ:street>
<typ:zip></typ:zip>
<typ:ico></typ:ico>
<typ:dic></typ:dic>
</typ:address>
</inv:partnerIdentity>
<inv:paymentType>
<typ:paymentType>draft</typ:paymentType>
</inv:paymentType>
<inv:note>Na�teno z XML</inv:note>
</inv:invoiceHeader>
<inv:invoiceSummary>
<inv:homeCurrency>
<typ:priceNone>500</typ:priceNone>
<typ:priceLow>0</typ:priceLow>
<typ:priceLowVAT>0</typ:priceLowVAT>
<typ:priceHigh>0</typ:priceHigh>
<typ:priceHighVAT>0</typ:priceHighVAT>
</inv:homeCurrency>
</inv:invoiceSummary>
</inv:invoice>
</dat:dataPackItem>
</dat:dataPack>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment