summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexis de Lattre <alexis.delattre@akretion.com>2017-09-09 23:56:48 (GMT)
committerAlexis de Lattre <alexis.delattre@akretion.com>2017-09-09 23:56:48 (GMT)
commitabadc914fa63266da99c543817c96df49d08c444 (patch)
tree994d2c7181e6e0a7aa2259eb19ca36abed23e7f6
parent4d97a4933b63c220ede49efe198cf132abc82fea (diff)
downloadfactur-x-abadc914fa63266da99c543817c96df49d08c444.zip
factur-x-abadc914fa63266da99c543817c96df49d08c444.tar.gz
factur-x-abadc914fa63266da99c543817c96df49d08c444.tar.bz2
Initial check-in
-rw-r--r--LICENSE24
-rw-r--r--MANIFEST.in16
-rw-r--r--README.rst47
-rwxr-xr-xbin/facturx-pdfextractxml95
-rwxr-xr-xbin/facturx-pdfgen137
-rwxr-xr-xbin/facturx-xmlcheck85
-rw-r--r--facturx/.factur-x.py.swpbin0 -> 36864 bytes
-rw-r--r--facturx/__init__.py3
-rw-r--r--facturx/facturx.py553
-rw-r--r--facturx/xmp/Factur-X_extension_schema.xmp79
-rw-r--r--facturx/xmp/ZUGFeRD_extension_schema.xmp99
-rw-r--r--facturx/xsd/factur-x/Factur-X_BASIC_WL.xsd20
-rw-r--r--facturx/xsd/factur-x/Factur-X_BASIC_WL_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd89
-rw-r--r--facturx/xsd/factur-x/Factur-X_BASIC_WL_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd190
-rw-r--r--facturx/xsd/factur-x/Factur-X_BASIC_WL_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd54
-rw-r--r--facturx/xsd/factur-x/Factur-X_EN16931.xsd20
-rw-r--r--facturx/xsd/factur-x/Factur-X_EN16931_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd97
-rw-r--r--facturx/xsd/factur-x/Factur-X_EN16931_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd320
-rw-r--r--facturx/xsd/factur-x/Factur-X_EN16931_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd85
-rw-r--r--facturx/xsd/zugferd/ZUGFeRD1p0.xsd20
-rw-r--r--facturx/xsd/zugferd/ZUGFeRD1p0_urn_un_unece_uncefact_data_standard_QualifiedDataType_12.xsd76
-rw-r--r--facturx/xsd/zugferd/ZUGFeRD1p0_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_12.xsd352
-rw-r--r--facturx/xsd/zugferd/ZUGFeRD1p0_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_15.xsd95
-rw-r--r--requirement.txt2
-rw-r--r--setup.py32
25 files changed, 2590 insertions, 0 deletions
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..5671a12
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,24 @@
+Copyright (c) 2016-2017, Alexis de Lattre <alexis.delattre@akretion.com>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * The name of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..5ac8f53
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,16 @@
+include README.rst
+include requirement.txt
+include facturx/xsd/zugferd/ZUGFeRD1p0_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_12.xsd
+include facturx/xsd/zugferd/ZUGFeRD1p0_urn_un_unece_uncefact_data_standard_QualifiedDataType_12.xsd
+include facturx/xsd/zugferd/ZUGFeRD1p0_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_15.xsd
+include facturx/xsd/zugferd/ZUGFeRD1p0.xsd
+include facturx/xsd/factur-x/Factur-X_BASIC_WL_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
+include facturx/xsd/factur-x/Factur-X_EN16931_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd
+include facturx/xsd/factur-x/Factur-X_EN16931_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
+include facturx/xsd/factur-x/Factur-X_BASIC_WL_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd
+include facturx/xsd/factur-x/Factur-X_EN16931.xsd
+include facturx/xsd/factur-x/Factur-X_EN16931_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd
+include facturx/xsd/factur-x/Factur-X_BASIC_WL_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd
+include facturx/xsd/factur-x/Factur-X_BASIC_WL.xsd
+include facturx/xmp/ZUGFeRD_extension_schema.xmp
+include facturx/xmp/Factur-X_extension_schema.xmp
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..968d691
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,47 @@
+Factur-X Python library
+=======================
+
+Factur-X is the e-invoicing standard for France and Germany. The Factur-X specifications are available on the `FNFE-MPE website <http://fnfe-mpe.org/factur-x/>`_.
+
+The main feature of this Python library is to generate Factur-X invoices from a regular PDF invoice and a Factur-X compliant XML file.
+
+This lib provides additionnal features such as:
+
+* extract the Factur-X XML file from a Factur-X PDF invoice,
+* check a Factur-X XML file against the official XML Schema Definition.
+
+Some of the features provided by this lib also work for the ZUGFeRD e-invoicing standard (the ancestor of the Factur-X standard).
+
+Installation
+============
+
+```
+sudo pip install --upgrade factur-x
+```
+
+Usage
+=====
+
+```
+from facturx import generate_facturx
+
+facturx_pdf_invoice = generate_facturx(regular_pdf_invoice, facturx_xml_file)
+```
+
+To have more examples, look at the source code of the command line tools located in the *bin* subdirectory.
+
+Command line tools
+==================
+
+Several command line tools are provided with this lib:
+
+* facturx-pdfgen: generate a Factur-X PDF invoice from a regular PDF invoice and an XML file
+* facturx-pdfextractxml: extract the Factur-X XML file from a Factur-X PDF invoice
+* facturx-xmlcheck: check a Factur-X XML file against the official Factur-X XML Schema Definition
+
+All these commande line tools have a **-h** option that explains how to use them and shows all the available options.
+
+Contributors
+============
+
+* Alexis de Lattre <alexis.delattre@akretion.com>
diff --git a/bin/facturx-pdfextractxml b/bin/facturx-pdfextractxml
new file mode 100755
index 0000000..2f2c6eb
--- /dev/null
+++ b/bin/facturx-pdfextractxml
@@ -0,0 +1,95 @@
+#! /usr/bin/python
+# -*- coding: utf-8 -*-
+# © 2017 Alexis de Lattre <alexis.delattre@akretion.com>
+
+from optparse import OptionParser
+import sys
+from facturx import get_facturx_xml_from_pdf
+from facturx.facturx import logger
+import logging
+from os.path import isfile, isdir
+
+__author__ = "Alexis de Lattre <alexis.delattre@akretion.com>"
+__date__ = "August 2017"
+__version__ = "0.1"
+
+options = [
+ {'names': ('-l', '--log-level'), 'dest': 'log_level',
+ 'action': 'store', 'default': 'info',
+ 'help': "Set log level. Possible values: debug, info, warn, error. "
+ "Default value: info."},
+ {'names': ('-d', '--disable-xsd-check'), 'dest': 'disable_xsd_check',
+ 'action': 'store_true', 'default': False,
+ 'help': "De-activate XML Schema Definition check on Factur-X XML file "
+ "(the check is enabled by default)"},
+ ]
+
+
+def main(options, arguments):
+ if options.log_level:
+ log_level = options.log_level.lower()
+ log_map = {
+ 'debug': logging.DEBUG,
+ 'info': logging.INFO,
+ 'warn': logging.WARN,
+ 'error': logging.ERROR,
+ }
+ if log_level in log_map:
+ logger.setLevel(log_map[log_level])
+ else:
+ logger.error(
+ 'Wrong value for log level (%s). Possible values: %s',
+ log_level, ', '.join(log_map.keys()))
+ sys.exit(1)
+
+ if len(arguments) != 2:
+ logger.error(
+ 'This command requires 2 arguments (%d used). '
+ 'Use --help to get the details.', len(arguments))
+ sys.exit(1)
+ pdf_filename = arguments[0]
+ out_xml_filename = arguments[1]
+ if not isfile(pdf_filename):
+ logger.error('Argument %s is not a filename', pdf_filename)
+ sys.exit(1)
+ if isdir(out_xml_filename):
+ logger.error(
+ '2nd argument %s is a directory name (should be a the '
+ 'output XML filename)', out_xml_filename)
+ sys.exit(1)
+ pdf_file = open(pdf_filename)
+ check_xsd = True
+ if options.disable_xsd_check:
+ check_xsd = False
+ # The important line of code is below !
+ try:
+ (xml_filename, xml_string) = get_facturx_xml_from_pdf(
+ pdf_file, check_xsd=check_xsd)
+ except Exception, e:
+ logger.error(e)
+ sys.exit(1)
+ if xml_filename and xml_string:
+ if isfile(out_xml_filename):
+ logger.warn(
+ 'File %s already exists. Overwriting it!', out_xml_filename)
+ xml_file = open(out_xml_filename, 'w')
+ xml_file.write(xml_string)
+ xml_file.close()
+ logger.info('File %s generated', out_xml_filename)
+ else:
+ logger.warn('File %s has not been created', out_xml_filename)
+ sys.exit(1)
+
+
+if __name__ == '__main__':
+ usage = "Usage: facturx-pdfextractxml <invoice.pdf> <factur-x_xml.xml>"
+ epilog = "Author: %s\n\nVersion: %s" % (__author__, __version__)
+ description = "This extracts the XML file from a Factur-X invoice."
+ parser = OptionParser(usage=usage, epilog=epilog, description=description)
+ for option in options:
+ param = option['names']
+ del option['names']
+ parser.add_option(*param, **option)
+ options, arguments = parser.parse_args()
+ sys.argv[:] = arguments
+ main(options, arguments)
diff --git a/bin/facturx-pdfgen b/bin/facturx-pdfgen
new file mode 100755
index 0000000..1f8e42b
--- /dev/null
+++ b/bin/facturx-pdfgen
@@ -0,0 +1,137 @@
+#! /usr/bin/python
+# -*- coding: utf-8 -*-
+# © 2017 Alexis de Lattre <alexis.delattre@akretion.com>
+
+from optparse import OptionParser
+import sys
+from facturx import generate_facturx
+from facturx.facturx import logger
+import logging
+from os.path import isfile, isdir
+
+__author__ = "Alexis de Lattre <alexis.delattre@akretion.com>"
+__date__ = "August 2017"
+__version__ = "0.1"
+
+options = [
+ {'names': ('-l', '--log-level'), 'dest': 'log_level',
+ 'action': 'store', 'default': 'info',
+ 'help': "Set log level. Possible values: debug, info, warn, error. "
+ "Default value: info."},
+ {'names': ('-d', '--disable-xsd-check'), 'dest': 'disable_xsd_check',
+ 'action': 'store_true', 'default': False,
+ 'help': "De-activate XML Schema Definition check on Factur-X XML file "
+ "(the check is enabled by default)"},
+ {'names': ('-n', '--facturx-level'), 'dest': 'facturx_level',
+ 'action': 'store', 'default': 'autodetect',
+ 'help': "Specify the Factur-X level of the XML file. "
+ "Default: autodetect. If you specify a particular level instead of "
+ "using autodetection, you will win a very small amount of time "
+ "(less than 1 millisecond). "
+ "Possible values: minimum, basicwl, basic, en16931."},
+ {'names': ('-a', '--meta-author'), 'dest': 'meta_author',
+ 'action': 'store', 'default': False,
+ 'help': "Specify the author for PDF metadata. Default: use the vendor "
+ "name extracted from the Factur-X XML file."},
+ {'names': ('-k', '--meta-keywords'), 'dest': 'meta_keywords',
+ 'action': 'store', 'default': False,
+ 'help': "Specify the keywords for PDF metadata. "
+ "Default: 'Invoice, Factur-X'."},
+ {'names': ('-t', '--meta-title'), 'dest': 'meta_title',
+ 'action': 'store', 'default': False,
+ 'help': "Specify the title of PDF metadata. "
+ "Default: generic English title with information extracted from "
+ "the Factur-X XML file such as: 'Akretion: Invoice I1242'"},
+ {'names': ('-s', '--meta-subject'), 'dest': 'meta_subject',
+ 'action': 'store', 'default': False,
+ 'help': "Specify the subject of PDF metadata. "
+ "Default: generic English subject with information extracted from the "
+ "Factur-X XML file such as: "
+ "'Factur-X invoice I1242 dated 2017-08-17 issued by Akretion'"},
+ ]
+
+
+def main(options, arguments):
+ if options.log_level:
+ log_level = options.log_level.lower()
+ log_map = {
+ 'debug': logging.DEBUG,
+ 'info': logging.INFO,
+ 'warn': logging.WARN,
+ 'error': logging.ERROR,
+ }
+ if log_level in log_map:
+ logger.setLevel(log_map[log_level])
+ else:
+ logger.error(
+ 'Wrong value for log level (%s). Possible values: %s',
+ log_level, ', '.join(log_map.keys()))
+ sys.exit(1)
+
+ if len(arguments) != 3:
+ logger.error(
+ 'This command requires 3 arguments (%d used). '
+ 'Use --help to get the details.', len(arguments))
+ sys.exit(1)
+ pdf_filename = arguments[0]
+ xml_filename = arguments[1]
+ facturx_pdf_filename = arguments[2]
+ for filename in [pdf_filename, xml_filename]:
+ if not isfile(filename):
+ logger.error('Argument %s is not a filename', filename)
+ sys.exit(1)
+ if isdir(facturx_pdf_filename):
+ logger.error(
+ '3rd argument %s is a directory name (should be a the '
+ 'Factur-X PDF filename)', facturx_pdf_filename)
+ sys.exit(1)
+ pdf_file = open(pdf_filename)
+ xml_file = open(xml_filename)
+ check_xsd = True
+ if options.disable_xsd_check:
+ check_xsd = False
+ pdf_metadata = None
+ if (
+ options.meta_author or
+ options.meta_keywords or
+ options.meta_title or
+ options.meta_subject):
+ pdf_metadata = {
+ 'author': options.meta_author,
+ 'keywords': options.meta_keywords,
+ 'title': options.meta_title,
+ 'subject': options.meta_subject,
+ }
+ # The important line of code is below !
+ try:
+ pdf_content = generate_facturx(
+ pdf_file, xml_file, check_xsd=check_xsd,
+ facturx_level=options.facturx_level, pdf_metadata=pdf_metadata)
+ except Exception, e:
+ logger.error(e)
+ sys.exit(1)
+ if isfile(facturx_pdf_filename):
+ logger.warn(
+ 'File %s already exists. Overwriting it!', facturx_pdf_filename)
+ facturx_pdf_file = open(facturx_pdf_filename, 'w')
+ facturx_pdf_file.write(pdf_content)
+ facturx_pdf_file.close()
+
+
+if __name__ == '__main__':
+ usage = "Usage: facturx-pdfgen <regular_invoice.pdf> <factur-x_xml.xml> "\
+ "<facturx_invoice.pdf>\n"\
+ "\nIf you use one of the --meta-* arguments, you should specify "\
+ "all the meta-* arguments because the default values for "\
+ "metadata only apply if none of the meta-* arguments are used."
+ epilog = "Author: %s\n\nVersion: %s" % (__author__, __version__)
+ description = "This script generate a Factur-X PDF invoice from a "\
+ "regular PDF invoice and a Factur-X XML file."
+ parser = OptionParser(usage=usage, epilog=epilog, description=description)
+ for option in options:
+ param = option['names']
+ del option['names']
+ parser.add_option(*param, **option)
+ options, arguments = parser.parse_args()
+ sys.argv[:] = arguments
+ main(options, arguments)
diff --git a/bin/facturx-xmlcheck b/bin/facturx-xmlcheck
new file mode 100755
index 0000000..eebfe87
--- /dev/null
+++ b/bin/facturx-xmlcheck
@@ -0,0 +1,85 @@
+#! /usr/bin/python
+# -*- coding: utf-8 -*-
+# © 2017 Alexis de Lattre <alexis.delattre@akretion.com>
+
+from optparse import OptionParser
+import sys
+from facturx import check_facturx_xsd
+from facturx.facturx import logger
+import logging
+from os.path import isfile
+
+__author__ = "Alexis de Lattre <alexis.delattre@akretion.com>"
+__date__ = "August 2017"
+__version__ = "0.1"
+
+options = [
+ {'names': ('-l', '--log-level'), 'dest': 'log_level',
+ 'action': 'store', 'default': 'info',
+ 'help': "Set log level. Possible values: debug, info, warn, error. "
+ "Default value: info."},
+ {'names': ('-f', '--flavor'), 'dest': 'flavor',
+ 'action': 'store', 'default': 'autodetect',
+ 'help': "Set XML flavor. "
+ "Possible values: factur-x, zugferd or autodetect. "
+ "Default value: autodetect."},
+ {'names': ('-n', '--facturx-level'), 'dest': 'facturx_level',
+ 'action': 'store', 'default': 'autodetect',
+ 'help': "Specify the Factur-X level of the XML file. "
+ "Default: autodetect. If you specify a particular level instead of "
+ "using autodetection, you will win a very small amount of time "
+ "(less than 1 millisecond). "
+ "Possible values: minimum, basicwl, basic, en16931."},
+ ]
+
+
+def main(options, arguments):
+ if options.log_level:
+ log_level = options.log_level.lower()
+ log_map = {
+ 'debug': logging.DEBUG,
+ 'info': logging.INFO,
+ 'warn': logging.WARN,
+ 'error': logging.ERROR,
+ }
+ if log_level in log_map:
+ logger.setLevel(log_map[log_level])
+ else:
+ logger.error(
+ 'Wrong value for log level (%s). Possible values: %s',
+ log_level, ', '.join(log_map.keys()))
+ sys.exit(1)
+
+ if len(arguments) != 1:
+ logger.error(
+ 'This command requires 1 argument (%d used). '
+ 'Use --help to get the details.', len(arguments))
+ sys.exit(1)
+ xml_filename = arguments[0]
+ if not isfile(xml_filename):
+ logger.error('%s is not a filename', xml_filename)
+ sys.exit(1)
+ xml_file = open(xml_filename)
+ # The important line of code is below !
+ try:
+ check_facturx_xsd(
+ xml_file, flavor=options.flavor,
+ facturx_level=options.facturx_level)
+ except Exception, e:
+ logger.error(e)
+ sys.exit(1)
+
+
+if __name__ == '__main__':
+ usage = "Usage: facturx-xmlcheck <factur-x_xml.xml>\n"
+ epilog = "Author: %s\n\nVersion: %s" % (__author__, __version__)
+ description = "This script checks the Factur-X XML against the XML "\
+ "Schema Definition."
+ parser = OptionParser(usage=usage, epilog=epilog, description=description)
+ for option in options:
+ param = option['names']
+ del option['names']
+ parser.add_option(*param, **option)
+ options, arguments = parser.parse_args()
+ sys.argv[:] = arguments
+ main(options, arguments)
diff --git a/facturx/.factur-x.py.swp b/facturx/.factur-x.py.swp
new file mode 100644
index 0000000..33a1bb5
--- /dev/null
+++ b/facturx/.factur-x.py.swp
Binary files differ
diff --git a/facturx/__init__.py b/facturx/__init__.py
new file mode 100644
index 0000000..044af62
--- /dev/null
+++ b/facturx/__init__.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+
+from facturx import generate_facturx, get_facturx_flavor, get_facturx_level, check_facturx_xsd, get_facturx_xml_from_pdf
diff --git a/facturx/facturx.py b/facturx/facturx.py
new file mode 100644
index 0000000..e1d70ea
--- /dev/null
+++ b/facturx/facturx.py
@@ -0,0 +1,553 @@
+# -*- coding: utf-8 -*-
+# © 2016-2017, Alexis de Lattre <alexis.delattre@akretion.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * The name of the authors may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# TODO list:
+# - python3 support
+# - automated tests
+
+from StringIO import StringIO
+from lxml import etree
+from tempfile import NamedTemporaryFile
+from datetime import datetime
+from PyPDF2 import PdfFileWriter, PdfFileReader
+from PyPDF2.generic import DictionaryObject, DecodedStreamObject,\
+ NameObject, createStringObject, ArrayObject
+import os.path
+from pkg_resources import resource_filename
+import logging
+
+FORMAT = '%(asctime)s [%(levelname)s] %(message)s'
+logging.basicConfig(format=FORMAT)
+logger = logging.getLogger('factur-x')
+logger.setLevel(logging.INFO)
+
+FACTURX_FILENAME = 'factur-x.xml'
+FACTURX_LEVEL2xsd = {
+ 'minimum': 'Factur-X_BASIC_WL.xsd',
+ 'basicwl': 'Factur-X_BASIC_WL.xsd',
+ 'basic': 'Factur-X_EN16931.xsd',
+ 'en16931': 'Factur-X_EN16931.xsd', # comfort
+}
+
+
+def check_facturx_xsd(
+ facturx_xml, flavor='autodetect', facturx_level='autodetect'):
+ """
+ Validate the XML file against the XSD
+ :param facturx_xml: the Factur-X XML
+ :type facturx_xml: string, file or etree object
+ :param flavor: possible values: 'factur-x', 'zugferd' or 'autodetect'
+ :type flavor: string
+ :param facturx_level: the level of the Factur-X XML file. Default value
+ is 'autodetect'. The only advantage to specifiy a particular value instead
+ of using the autodetection is for a small perf improvement.
+ Possible values: minimum, basicwl, basic, en16931.
+ :return: True if the XML is valid against the XSD
+ raise an error if it is not valid against the XSD
+ """
+ assert facturx_xml, 'Missing facturx_xml arg'
+ assert isinstance(flavor, (str, unicode)), 'wrong type for flavor arg'
+ assert isinstance(facturx_level, (type(None), str, unicode)),\
+ 'wrong type for facturx_level arg'
+ facturx_xml_etree = None
+ if isinstance(facturx_xml, str):
+ xml_string = facturx_xml
+ elif isinstance(facturx_xml, unicode):
+ xml_string = facturx_xml.encode('utf8')
+ elif isinstance(facturx_xml, type(etree.Element('pouet'))):
+ facturx_xml_etree = facturx_xml
+ xml_string = etree.tostring(
+ facturx_xml, pretty_print=True, encoding='UTF-8',
+ xml_declaration=True)
+ elif isinstance(facturx_xml, file):
+ facturx_xml.seek(0)
+ xml_string = facturx_xml.read()
+ facturx_xml.close()
+
+ if flavor not in ('factur-x', 'facturx', 'zugferd'): # autodetect
+ if facturx_xml_etree is None:
+ try:
+ facturx_xml_etree = etree.fromstring(xml_string)
+ except Exception, e:
+ raise Exception(
+ "The XML syntax is invalid: %s." % unicode(e))
+ flavor = get_facturx_flavor(facturx_xml_etree)
+ if flavor in ('factur-x', 'facturx'):
+ if facturx_level not in FACTURX_LEVEL2xsd:
+ if facturx_xml_etree is None:
+ try:
+ facturx_xml_etree = etree.fromstring(xml_string)
+ except Exception, e:
+ raise Exception(
+ "The XML syntax is invalid: %s." % unicode(e))
+ facturx_level = get_facturx_level(facturx_xml_etree)
+ if facturx_level not in FACTURX_LEVEL2xsd:
+ raise ValueError(
+ "Wrong level '%s' for Factur-X invoice." % facturx_level)
+ xsd_filename = FACTURX_LEVEL2xsd[facturx_level]
+ xsd_file = resource_filename(
+ __name__, 'xsd/factur-x/%s' % xsd_filename)
+ elif flavor == 'zugferd':
+ xsd_file = resource_filename(
+ __name__, 'xsd/xsd-zugferd/ZUGFeRD1p0.xsd')
+ xsd_etree_obj = etree.parse(open(xsd_file))
+ official_schema = etree.XMLSchema(xsd_etree_obj)
+ try:
+ t = etree.parse(StringIO(xml_string))
+ official_schema.assertValid(t)
+ logger.info('Factur-X XML file successfully validated against XSD')
+ except Exception, e:
+ # if the validation of the XSD fails, we arrive here
+ logger.error(
+ "The XML file is invalid against the XML Schema Definition")
+ logger.error(xml_string)
+ raise Exception(
+ "The %s XML file is not valid against the official "
+ "XML Schema Definition. The XML file and the "
+ "full error have been written in the server logs. "
+ "Here is the error, which may give you an idea on the "
+ "cause of the problem: %s." % (flavor.capitalize(), unicode(e)))
+ return True
+
+
+def get_facturx_xml_from_pdf(pdf_invoice, check_xsd=True):
+ assert pdf_invoice, 'Missing pdf_invoice arg'
+ assert isinstance(check_xsd, bool), 'Missing pdf_invoice arg'
+ if isinstance(pdf_invoice, str):
+ pdf_file = StringIO(pdf_invoice)
+ elif isinstance(pdf_invoice, file):
+ pdf_file = pdf_invoice
+ else:
+ raise TypeError(
+ "The first argument of the methodPDFisFacturXInvoice must be "
+ "either a string or a file (it is a %s)." % type(pdf_invoice))
+ xml_string = xml_filename = False
+ try:
+ pdf = PdfFileReader(pdf_file)
+ pdf_root = pdf.trailer['/Root']
+ logger.debug('pdf_root=%s', pdf_root)
+ embeddedfiles = pdf_root['/Names']['/EmbeddedFiles']['/Names']
+ i = 0
+ for embeddedfile in embeddedfiles[:-1]:
+ if embeddedfile in (FACTURX_FILENAME, 'ZUGFeRD-invoice.xml'):
+ xml_file_dict = embeddedfiles[i+1].getObject()
+ logger.debug('xml_file_dict=%s', xml_file_dict)
+ tmp_xml_string = xml_file_dict['/EF']['/F'].getData()
+ xml_root = etree.fromstring(tmp_xml_string)
+ logger.info(
+ 'A valid XML file %s has been found in the PDF file',
+ embeddedfile)
+ if check_xsd:
+ check_facturx_xsd(xml_root)
+ xml_string = tmp_xml_string
+ xml_filename = embeddedfile
+ else:
+ xml_string = tmp_xml_string
+ xml_filename = embeddedfile
+ break
+ except:
+ logger.error('No valid XML file found in the PDF')
+ return (None, None)
+ logger.info('Returning an XML file %s', xml_filename)
+ logger.debug('Content of the XML file: %s', xml_string)
+ return (xml_filename, xml_string)
+
+
+def _get_pdf_timestamp():
+ now_dt = datetime.now()
+ # example date format: "D:20141006161354+02'00'"
+ pdf_date = now_dt.strftime("D:%Y%m%d%H%M%S+00'00'")
+ return pdf_date
+
+
+def _get_metadata_timestamp():
+ now_dt = datetime.now()
+ # example format : 2014-07-25T14:01:22+02:00
+ meta_date = now_dt.strftime('%Y-%m-%dT%H:%M:%S+00:00')
+ return meta_date
+
+
+def _prepare_pdf_metadata_txt(pdf_metadata):
+ pdf_date = _get_pdf_timestamp()
+ info_dict = {
+ '/Author': pdf_metadata.get('author', ''),
+ '/CreationDate': pdf_date,
+ '/Creator': u'factur-x Python lib by Alexis de Lattre',
+ '/Keywords': pdf_metadata.get('keywords', ''),
+ '/ModDate': pdf_date,
+ '/Subject': pdf_metadata.get('subject', ''),
+ '/Title': pdf_metadata.get('title', ''),
+ }
+ return info_dict
+
+
+def _prepare_pdf_metadata_xml(facturx_level, pdf_metadata):
+ nsmap_rdf = {'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'}
+ nsmap_dc = {'dc': 'http://purl.org/dc/elements/1.1/'}
+ nsmap_pdf = {'pdf': 'http://ns.adobe.com/pdf/1.3/'}
+ nsmap_xmp = {'xmp': 'http://ns.adobe.com/xap/1.0/'}
+ nsmap_pdfaid = {'pdfaid': 'http://www.aiim.org/pdfa/ns/id/'}
+ nsmap_fx = {
+ 'fx': 'urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#'}
+ ns_dc = '{%s}' % nsmap_dc['dc']
+ ns_rdf = '{%s}' % nsmap_rdf['rdf']
+ ns_pdf = '{%s}' % nsmap_pdf['pdf']
+ ns_xmp = '{%s}' % nsmap_xmp['xmp']
+ ns_pdfaid = '{%s}' % nsmap_pdfaid['pdfaid']
+ ns_fx = '{%s}' % nsmap_fx['fx']
+ ns_xml = '{http://www.w3.org/XML/1998/namespace}'
+
+ root = etree.Element(ns_rdf + 'RDF', nsmap=nsmap_rdf)
+ desc_pdfaid = etree.SubElement(
+ root, ns_rdf + 'Description', nsmap=nsmap_pdfaid)
+ desc_pdfaid.set(ns_rdf + 'about', '')
+ etree.SubElement(
+ desc_pdfaid, ns_pdfaid + 'part').text = '3'
+ etree.SubElement(
+ desc_pdfaid, ns_pdfaid + 'conformance').text = 'B'
+ desc_dc = etree.SubElement(
+ root, ns_rdf + 'Description', nsmap=nsmap_dc)
+ desc_dc.set(ns_rdf + 'about', '')
+ dc_title = etree.SubElement(desc_dc, ns_dc + 'title')
+ dc_title_alt = etree.SubElement(dc_title, ns_rdf + 'Alt')
+ dc_title_alt_li = etree.SubElement(
+ dc_title_alt, ns_rdf + 'li')
+ dc_title_alt_li.text = pdf_metadata.get('title', '')
+ dc_title_alt_li.set(ns_xml + 'lang', 'x-default')
+ dc_creator = etree.SubElement(desc_dc, ns_dc + 'creator')
+ dc_creator_seq = etree.SubElement(dc_creator, ns_rdf + 'Seq')
+ etree.SubElement(
+ dc_creator_seq, ns_rdf + 'li').text = pdf_metadata.get('author', '')
+ dc_desc = etree.SubElement(desc_dc, ns_dc + 'description')
+ dc_desc_alt = etree.SubElement(dc_desc, ns_rdf + 'Alt')
+ dc_desc_alt_li = etree.SubElement(
+ dc_desc_alt, ns_rdf + 'li')
+ dc_desc_alt_li.text = pdf_metadata.get('subject', '')
+ dc_desc_alt_li.set(ns_xml + 'lang', 'x-default')
+ desc_adobe = etree.SubElement(
+ root, ns_rdf + 'Description', nsmap=nsmap_pdf)
+ desc_adobe.set(ns_rdf + 'about', '')
+ producer = etree.SubElement(
+ desc_adobe, ns_pdf + 'Producer')
+ producer.text = 'PyPDF2'
+ desc_xmp = etree.SubElement(
+ root, ns_rdf + 'Description', nsmap=nsmap_xmp)
+ desc_xmp.set(ns_rdf + 'about', '')
+ creator = etree.SubElement(
+ desc_xmp, ns_xmp + 'CreatorTool')
+ creator.text = 'factur-x python lib by Alexis de Lattre'
+ timestamp = _get_metadata_timestamp()
+ etree.SubElement(desc_xmp, ns_xmp + 'CreateDate').text = timestamp
+ etree.SubElement(desc_xmp, ns_xmp + 'ModifyDate').text = timestamp
+
+ xmp_file = resource_filename(
+ __name__, 'xmp/Factur-X_extension_schema.xmp')
+ facturx_ext_schema_root = etree.parse(open(xmp_file))
+ # The Factur-X extension schema must be embedded into each PDF document
+ facturx_ext_schema_desc_xpath = facturx_ext_schema_root.xpath(
+ '//rdf:Description', namespaces=nsmap_rdf)
+ root.append(facturx_ext_schema_desc_xpath[1])
+ # Now is the Factur-X description tag
+ facturx_desc = etree.SubElement(
+ root, ns_rdf + 'Description', nsmap=nsmap_fx)
+ facturx_desc.set(ns_rdf + 'about', '')
+ facturx_desc.set(ns_fx + 'ConformanceLevel', facturx_level.upper())
+ facturx_desc.set(ns_fx + 'DocumentFileName', FACTURX_FILENAME)
+ facturx_desc.set(ns_fx + 'DocumentType', 'INVOICE')
+ facturx_desc.set(ns_fx + 'Version', '1.0')
+
+ xml_str = etree.tostring(
+ root, pretty_print=True, encoding="UTF-8", xml_declaration=False)
+ logger.debug('metadata XML:')
+ logger.debug(xml_str)
+ return xml_str
+
+
+def _facturx_update_metadata_add_attachment(
+ pdf_filestream, facturx_xml_str, pdf_metadata, facturx_level):
+ '''This method is inspired from the code of the addAttachment()
+ method of the PyPDF2 lib'''
+ # The entry for the file
+ moddate = DictionaryObject()
+ moddate.update({
+ NameObject('/ModDate'): createStringObject(_get_pdf_timestamp())})
+ file_entry = DecodedStreamObject()
+ file_entry.setData(facturx_xml_str)
+ file_entry.update({
+ NameObject("/Type"): NameObject("/EmbeddedFile"),
+ NameObject("/Params"): moddate,
+ # 2F is '/' in hexadecimal
+ NameObject("/Subtype"): NameObject("/text#2Fxml"),
+ })
+ file_entry_obj = pdf_filestream._addObject(file_entry)
+ # The Filespec entry
+ efEntry = DictionaryObject()
+ efEntry.update({
+ NameObject("/F"): file_entry_obj,
+ NameObject('/UF'): file_entry_obj,
+ })
+
+ fname_obj = createStringObject(FACTURX_FILENAME)
+ filespec = DictionaryObject()
+ filespec.update({
+ NameObject("/AFRelationship"): NameObject("/Alternative"),
+ NameObject("/Desc"): createStringObject("Factur-X Invoice"),
+ NameObject("/Type"): NameObject("/Filespec"),
+ NameObject("/F"): fname_obj,
+ NameObject("/EF"): efEntry,
+ NameObject("/UF"): fname_obj,
+ })
+ embeddedFilesNamesDictionary = DictionaryObject()
+ embeddedFilesNamesDictionary.update({
+ NameObject("/Names"): ArrayObject(
+ [fname_obj, pdf_filestream._addObject(filespec)])
+ })
+ # Then create the entry for the root, as it needs a
+ # reference to the Filespec
+ embeddedFilesDictionary = DictionaryObject()
+ embeddedFilesDictionary.update({
+ NameObject("/EmbeddedFiles"): embeddedFilesNamesDictionary
+ })
+ # Update the root
+ metadata_xml_str = _prepare_pdf_metadata_xml(facturx_level, pdf_metadata)
+ metadata_file_entry = DecodedStreamObject()
+ metadata_file_entry.setData(metadata_xml_str)
+ metadata_value = pdf_filestream._addObject(metadata_file_entry)
+ af_value = pdf_filestream._addObject(
+ ArrayObject([pdf_filestream._addObject(filespec)]))
+ pdf_filestream._root_object.update({
+ NameObject("/AF"): af_value,
+ NameObject("/Metadata"): metadata_value,
+ NameObject("/Names"): embeddedFilesDictionary,
+ })
+ metadata_txt_dict = _prepare_pdf_metadata_txt(pdf_metadata)
+ pdf_filestream.addMetadata(metadata_txt_dict)
+
+
+def _extract_base_info(facturx_xml_etree):
+ namespaces = facturx_xml_etree.nsmap
+ date_xpath = facturx_xml_etree.xpath(
+ '//rsm:ExchangedDocument/ram:IssueDateTime/udt:DateTimeString',
+ namespaces=namespaces)
+ date = date_xpath[0].text
+ date_dt = datetime.strptime(date, '%Y%m%d')
+ inv_num_xpath = facturx_xml_etree.xpath(
+ '//rsm:ExchangedDocument/ram:ID', namespaces=namespaces)
+ inv_num = inv_num_xpath[0].text
+ seller_xpath = facturx_xml_etree.xpath(
+ '//ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:Name',
+ namespaces=namespaces)
+ seller = seller_xpath[0].text
+ doc_type_xpath = facturx_xml_etree.xpath(
+ '//rsm:ExchangedDocument/ram:TypeCode', namespaces=namespaces)
+ doc_type = doc_type_xpath[0].text
+ base_info = {
+ 'seller': seller,
+ 'number': inv_num,
+ 'date': date_dt,
+ 'doc_type': doc_type,
+ }
+ logger.debug('Extraction of base_info: %s', base_info)
+ return base_info
+
+
+def _base_info2pdf_metadata(base_info):
+ if base_info['doc_type'] == '381':
+ doc_type_name = u'Refund'
+ else:
+ doc_type_name = u'Invoice'
+ date_str = datetime.strftime(base_info['date'], '%Y-%m-%d')
+ title = '%s: %s %s' % (
+ base_info['seller'], doc_type_name, base_info['number'])
+ subject = 'Factur-X %s %s dated %s issued by %s' % (
+ doc_type_name, base_info['number'], date_str, base_info['seller'])
+ pdf_metadata = {
+ 'author': base_info['seller'],
+ 'keywords': u'%s, Factur-X' % doc_type_name,
+ 'title': title,
+ 'subject': subject,
+ }
+ logger.debug('Converted base_info to pdf_metadata: %s', pdf_metadata)
+ return pdf_metadata
+
+
+def get_facturx_level(facturx_xml_etree):
+ assert isinstance(facturx_xml_etree, type(etree.Element('pouet'))),\
+ 'facturx_xml_etree must be an etree.Element() object'
+ namespaces = facturx_xml_etree.nsmap
+ doc_id_xpath = facturx_xml_etree.xpath(
+ "//rsm:ExchangedDocumentContext"
+ "/ram:GuidelineSpecifiedDocumentContextParameter"
+ "/ram:ID", namespaces=namespaces)
+ if not doc_id_xpath:
+ raise ValueError(
+ "This XML is not a Factur-X XML because it misses the XML tag "
+ "ExchangedDocumentContext/"
+ "GuidelineSpecifiedDocumentContextParameter/ID.")
+ doc_id = doc_id_xpath[0].text
+ level = doc_id.split(':')[-1]
+ logger.info('Factur-X level is %s (autodetected)', level)
+ return level
+
+
+def get_facturx_flavor(facturx_xml_etree):
+ assert isinstance(facturx_xml_etree, type(etree.Element('pouet'))),\
+ 'facturx_xml_etree must be an etree.Element() object'
+ if facturx_xml_etree.tag.startswith('{urn:un:unece:uncefact:'):
+ flavor = 'factur-x'
+ elif facturx_xml_etree.tag.startswith('{urn:ferd:'):
+ flavor = 'zugferd'
+ else:
+ raise Exception(
+ "Could not detect if the invoice is a Factur-X or ZUGFeRD "
+ "invoice.")
+ logger.info('Factur-X flavor is %s (autodetected)', flavor)
+ return flavor
+
+
+def generate_facturx(
+ pdf_invoice, facturx_xml, facturx_level='autodetect',
+ check_xsd=True, pdf_metadata=None, output_pdf_file=None):
+ """
+ Generate a Factur-X invoice from a regular PDF invoice and a factur-X XML
+ file. This is the main method of this lib.
+ :param pdf_invoice: the regular PDF invoice
+ :type pdf_invoice: binary or file
+ :param facturx_xml: the Factur-X XML
+ :type facturx_xml: string, file or etree object
+ :param facturx_level: the level of the Factur-X XML file. Default value
+ is 'autodetect'. The only advantage to specifiy a particular value instead
+ of using the autodetection is for a very very small perf improvement.
+ Possible values: minimum, basicwl, basic, en16931.
+ :type facturx_level: string
+ :param check_xsd: if enable, checks the Factur-X XML file against the XSD
+ (XML Schema Definition). If this step has already been performed
+ beforehand, you should disable this feature to avoid a double check
+ and get a small performance improvement.
+ :type check_xsd: boolean
+ :param pdf_metadata: Specify the metadata of the generated Factur-X PDF.
+ If pdf_metadata is None (default value), this lib will generate some
+ metadata in English by extracting relevant info from the Factur-X XML.
+ Here is an example for the pdf_metadata argument:
+ pdf_metadata = {
+ 'author': 'Akretion',
+ 'keywords': 'Factur-X, Invoice',
+ 'title': 'Akretion: Invoice I1242',
+ 'subject':
+ 'Factur-X invoice I1242 dated 2017-08-17 issued by Akretion',
+ }
+ If you pass the pdf_metadata argument, you will not use the automatic
+ generation based on the extraction of the Factur-X XML file, which will
+ bring a very small perf improvement.
+ :type pdf_metadata: dict
+ """
+ start_chrono = datetime.now()
+ logger.debug('1st arg pdf_invoice type=%s', type(pdf_invoice))
+ logger.debug('2nd arg facturx_xml type=%s', type(facturx_xml))
+ logger.debug('optional arg facturx_level=%s', facturx_level)
+ logger.debug('optional arg check_xsd=%s', check_xsd)
+ logger.debug('optional arg pdf_metadata=%s', pdf_metadata)
+ assert pdf_invoice, 'Missing pdf_invoice arg'
+ assert facturx_xml, 'Missing facturx_xml arg'
+ assert isinstance(facturx_level, (str, unicode)), 'Wrong facturx_level arg'
+ assert isinstance(check_xsd, bool), 'check_xsd arg must be a boolean'
+ assert isinstance(pdf_metadata, (type(None), dict)),\
+ 'pdf_metadata must be a dict or None'
+ assert isinstance(output_pdf_file, (type(None), str)),\
+ 'output_pdf_file must be a string or None'
+ if isinstance(pdf_invoice, str):
+ original_pdf_file = StringIO(pdf_invoice)
+ elif isinstance(pdf_invoice, file):
+ original_pdf_file = pdf_invoice
+ else:
+ raise TypeError(
+ "The first argument of the method GenerateFacturX must be "
+ "either a string or a file (it is a %s)." % type(pdf_invoice))
+ xml_root = None
+ if isinstance(facturx_xml, str):
+ xml_string = facturx_xml
+ elif isinstance(facturx_xml, unicode):
+ xml_string = facturx_xml.encode('utf8')
+ elif isinstance(facturx_xml, type(etree.Element('pouet'))):
+ xml_root = facturx_xml
+ xml_string = etree.tostring(
+ xml_root, pretty_print=True, encoding='UTF-8',
+ xml_declaration=True)
+ elif isinstance(facturx_xml, file):
+ facturx_xml.seek(0)
+ xml_string = facturx_xml.read()
+ facturx_xml.close()
+ else:
+ raise TypeError(
+ "The second argument of the method GenerateFacturX must be "
+ "either a string, an etree.Element() object or a file "
+ "(it is a %s)." % type(facturx_xml))
+ if pdf_metadata is None:
+ if xml_root is None:
+ xml_root = etree.fromstring(xml_string)
+ base_info = _extract_base_info(xml_root)
+ pdf_metadata = _base_info2pdf_metadata(base_info)
+ else:
+ # clean-up pdf_metadata dict
+ for key, value in pdf_metadata.iteritems():
+ if not isinstance(value, (str, unicode)):
+ pdf_metadata[key] = ''
+ facturx_level = facturx_level.lower()
+ if facturx_level not in FACTURX_LEVEL2xsd:
+ if xml_root is None:
+ xml_root = etree.fromstring(xml_string)
+ logger.debug('Factur-X level will be autodetected')
+ facturx_level = get_facturx_level(xml_root)
+ if check_xsd:
+ check_facturx_xsd(
+ xml_string, flavor='factur-x', facturx_level=facturx_level)
+ assert isinstance(pdf_metadata, dict), 'pdf_metadata must be a dict'
+ original_pdf = PdfFileReader(original_pdf_file)
+ new_pdf_filestream = PdfFileWriter()
+ new_pdf_filestream.appendPagesFromReader(original_pdf)
+ _facturx_update_metadata_add_attachment(
+ new_pdf_filestream, xml_string, pdf_metadata, facturx_level)
+ pdf_content = True
+ if output_pdf_file:
+ if os.path.isdir(output_pdf_file):
+ raise ValueError(
+ "The argument output_pdf_file (%s) is a directory. "
+ "It must be a file." % output_pdf_file)
+ with open(output_pdf_file, 'w') as f:
+ new_pdf_filestream.write(f)
+ f.close()
+ else:
+ with NamedTemporaryFile(prefix='invoice-facturx-', suffix='.pdf') as f:
+ new_pdf_filestream.write(f)
+ f.seek(0)
+ pdf_content = f.read()
+ f.close()
+ logger.info('%s file added to PDF invoice', FACTURX_FILENAME)
+ end_chrono = datetime.now()
+ logger.info(
+ 'Factur-X invoice generated in %s seconds',
+ (end_chrono - start_chrono).total_seconds())
+ return pdf_content
diff --git a/facturx/xmp/Factur-X_extension_schema.xmp b/facturx/xmp/Factur-X_extension_schema.xmp
new file mode 100644
index 0000000..0639209
--- /dev/null
+++ b/facturx/xmp/Factur-X_extension_schema.xmp
@@ -0,0 +1,79 @@
+<!--
+PDFlib GmbH 2013-2014
+
+Sample FACTUR-X XMP with the required PDF/A extension schema description
+for the XMP properties of the FACTUR-X schema and the actual FACTUR-X properties.
+
+Schema name: FACTUR-X Schema
+Preferred schema namespace prefix: fx
+Schema namespace URI: urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#
+
+Notes on the Factur-X schema namespace URI:
+
+- The use of mixed upper/lowercase in "CrossIndustryDocument" conforms to
+ the Factur-X 1.0 specification. The PDF samples distributed with the
+ Factur-X 1.0 info package use all-lowercase spelling "crossindustrydocument"
+ which is not correct since it violates the Factur-X specification.
+
+- The required trailing "#" character is missing in the comment in the
+ Factur-X 1.0 extension schema description which is included in the Factur-X
+ specification, but it is correctly present in the actual XMP.
+
+
+-->
+<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+
+ <!-- The actual Factur-X properties; adjust if required -->
+ <rdf:Description rdf:about="" xmlns:fx="urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#">
+ <fx:ConformanceLevel>BASIC</fx:ConformanceLevel>
+ <fx:DocumentFileName>factur-x.xml</fx:DocumentFileName>
+ <fx:DocumentType>INVOICE</fx:DocumentType>
+ <fx:Version>1.0</fx:Version>
+ </rdf:Description>
+
+ <!-- PDF/A extension schema description for the Factur-X schema.
+ It is crucial for PDF/A-3 conformance. Don't touch! -->
+ <rdf:Description rdf:about=""
+ xmlns:pdfaExtension="http://www.aiim.org/pdfa/ns/extension/"
+ xmlns:pdfaSchema="http://www.aiim.org/pdfa/ns/schema#"
+ xmlns:pdfaProperty="http://www.aiim.org/pdfa/ns/property#">
+
+ <pdfaExtension:schemas>
+ <rdf:Bag>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaSchema:schema>Factur-X PDFA Extension Schema</pdfaSchema:schema>
+ <pdfaSchema:namespaceURI>urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#</pdfaSchema:namespaceURI>
+ <pdfaSchema:prefix>fx</pdfaSchema:prefix>
+ <pdfaSchema:property>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:name>DocumentFileName</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>name of the embedded XML invoice file</pdfaProperty:description>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:name>DocumentType</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>INVOICE</pdfaProperty:description>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:name>Version</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>The actual version of the Factur-X XML schema</pdfaProperty:description>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:name>ConformanceLevel</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>The conformance level of the embedded Factur-X data</pdfaProperty:description>
+ </rdf:li>
+ </rdf:Seq>
+ </pdfaSchema:property>
+ </rdf:li>
+ </rdf:Bag>
+ </pdfaExtension:schemas>
+ </rdf:Description>
+</rdf:RDF> \ No newline at end of file
diff --git a/facturx/xmp/ZUGFeRD_extension_schema.xmp b/facturx/xmp/ZUGFeRD_extension_schema.xmp
new file mode 100644
index 0000000..d5e068c
--- /dev/null
+++ b/facturx/xmp/ZUGFeRD_extension_schema.xmp
@@ -0,0 +1,99 @@
+<!--
+PDFlib GmbH 2013-2014
+
+Sample ZUGFeRD XMP with the required PDF/A extension schema description
+for the XMP properties of the ZUGFeRD schema and the actual ZUGFeRD properties.
+
+Schema name: ZUGFeRD Schema
+Preferred schema namespace prefix: zf
+Schema namespace URI: urn:ferd:pdfa:CrossIndustryDocument:invoice:1p0#
+
+Notes on the ZUGFeRD schema namespace URI:
+
+- The use of mixed upper/lowercase in "CrossIndustryDocument" conforms to
+ the ZUGFeRD 1.0 specification. The PDF samples distributed with the
+ ZUGFeRD 1.0 info package use all-lowercase spelling "crossindustrydocument"
+ which is not correct since it violates the ZUGFeRD specification.
+
+- The required trailing "#" character is missing in the comment in the
+ ZUGFeRD 1.0 extension schema description which is included in the ZUGFeRD
+ specification, but it is correctly present in the actual XMP.
+
+
+Based on the ZUGFeRD 1.0 package (published 2014-06 on www.ferd-net.de)
+which is Copyright AWV e.V. 2014.
+
+
+2014-07-01 (based on ZUGFeRD 1.0)
+Adjustments for ZUGFeRD 1.0:
+- updated header comments
+- switched to new namespace URI
+- adjusted property descriptions in the extension schema descriptions
+
+2013-06-19 (based on ZUGFeRD RC)
+Added a trailing hash character "#" to the "zf" namespace name as required
+by the XMP 2005 specification which is referenced in PDF/A-2 and PDF/A-3.
+Without this change Acrobat XI Preflight validation for PDF/A-3 complains
+"Extension schema present but not valid"
+
+2013-06-19
+Singled out the zf properties into a separate rdf:Description node to work
+around bug #4433 in PDFlib 9.0.0 which has been fixed in PDFlib 9.0.1.
+
+-->
+<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+
+ <!-- The actual ZUGFeRD properties; adjust if required -->
+ <rdf:Description rdf:about="" xmlns:zf="urn:ferd:pdfa:CrossIndustryDocument:invoice:1p0#">
+ <zf:ConformanceLevel>BASIC</zf:ConformanceLevel>
+ <zf:DocumentFileName>ZUGFeRD-invoice.xml</zf:DocumentFileName>
+ <zf:DocumentType>INVOICE</zf:DocumentType>
+ <zf:Version>1.0</zf:Version>
+ </rdf:Description>
+
+ <!-- PDF/A extension schema description for the ZUGFeRD schema.
+ It is crucial for PDF/A-3 conformance. Don't touch! -->
+ <rdf:Description rdf:about=""
+ xmlns:pdfaExtension="http://www.aiim.org/pdfa/ns/extension/"
+ xmlns:pdfaSchema="http://www.aiim.org/pdfa/ns/schema#"
+ xmlns:pdfaProperty="http://www.aiim.org/pdfa/ns/property#">
+
+ <pdfaExtension:schemas>
+ <rdf:Bag>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaSchema:schema>ZUGFeRD PDFA Extension Schema</pdfaSchema:schema>
+ <pdfaSchema:namespaceURI>urn:ferd:pdfa:CrossIndustryDocument:invoice:1p0#</pdfaSchema:namespaceURI>
+ <pdfaSchema:prefix>zf</pdfaSchema:prefix>
+ <pdfaSchema:property>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:name>DocumentFileName</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>name of the embedded XML invoice file</pdfaProperty:description>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:name>DocumentType</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>INVOICE</pdfaProperty:description>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:name>Version</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>The actual version of the ZUGFeRD XML schema</pdfaProperty:description>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:name>ConformanceLevel</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>The conformance level of the embedded ZUGFeRD data</pdfaProperty:description>
+ </rdf:li>
+ </rdf:Seq>
+ </pdfaSchema:property>
+ </rdf:li>
+ </rdf:Bag>
+ </pdfaExtension:schemas>
+ </rdf:Description>
+</rdf:RDF> \ No newline at end of file
diff --git a/facturx/xsd/factur-x/Factur-X_BASIC_WL.xsd b/facturx/xsd/factur-x/Factur-X_BASIC_WL.xsd
new file mode 100644
index 0000000..42d68ba
--- /dev/null
+++ b/facturx/xsd/factur-x/Factur-X_BASIC_WL.xsd
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:qdt="urn:un:unece:uncefact:data:standard:QualifiedDataType:100"
+ xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"
+ xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"
+ targetNamespace="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100"
+ elementFormDefault="qualified">
+ <xs:import namespace="urn:un:unece:uncefact:data:standard:QualifiedDataType:100" schemaLocation="Factur-X_BASIC_WL_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd"/>
+ <xs:import namespace="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100" schemaLocation="Factur-X_BASIC_WL_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd"/>
+ <xs:import namespace="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100" schemaLocation="Factur-X_BASIC_WL_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd"/>
+ <xs:element name="CrossIndustryInvoice" type="rsm:CrossIndustryInvoiceType"/>
+ <xs:complexType name="CrossIndustryInvoiceType">
+ <xs:sequence>
+ <xs:element name="ExchangedDocumentContext" type="ram:ExchangedDocumentContextType"/>
+ <xs:element name="ExchangedDocument" type="ram:ExchangedDocumentType"/>
+ <xs:element name="SupplyChainTradeTransaction" type="ram:SupplyChainTradeTransactionType"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:schema>
diff --git a/facturx/xsd/factur-x/Factur-X_BASIC_WL_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd b/facturx/xsd/factur-x/Factur-X_BASIC_WL_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd
new file mode 100644
index 0000000..908b8fd
--- /dev/null
+++ b/facturx/xsd/factur-x/Factur-X_BASIC_WL_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:qdt="urn:un:unece:uncefact:data:standard:QualifiedDataType:100"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"
+ targetNamespace="urn:un:unece:uncefact:data:standard:QualifiedDataType:100"
+ elementFormDefault="qualified"
+ version="100.D16B">
+ <xs:import namespace="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100" schemaLocation="Factur-X_BASIC_WL_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd"/>
+ <xs:simpleType name="AllowanceChargeReasonCodeContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="AllowanceChargeReasonCodeType">
+ <xs:simpleContent>
+ <xs:extension base="qdt:AllowanceChargeReasonCodeContentType"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="CountryIDContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="CountryIDType">
+ <xs:simpleContent>
+ <xs:extension base="qdt:CountryIDContentType"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="CurrencyCodeContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="CurrencyCodeType">
+ <xs:simpleContent>
+ <xs:extension base="qdt:CurrencyCodeContentType"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="DocumentCodeContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="DocumentCodeType">
+ <xs:simpleContent>
+ <xs:extension base="qdt:DocumentCodeContentType"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="FormattedDateTimeFormatContentType">
+ <xs:restriction base="xs:string"/>
+ </xs:simpleType>
+ <xs:complexType name="FormattedDateTimeType">
+ <xs:sequence>
+ <xs:element name="DateTimeString">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="format" type="qdt:FormattedDateTimeFormatContentType"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="PaymentMeansCodeContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="PaymentMeansCodeType">
+ <xs:simpleContent>
+ <xs:extension base="qdt:PaymentMeansCodeContentType"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="TaxCategoryCodeContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="TaxCategoryCodeType">
+ <xs:simpleContent>
+ <xs:extension base="qdt:TaxCategoryCodeContentType"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="TaxTypeCodeContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="TaxTypeCodeType">
+ <xs:simpleContent>
+ <xs:extension base="qdt:TaxTypeCodeContentType"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="TimeReferenceCodeContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="TimeReferenceCodeType">
+ <xs:simpleContent>
+ <xs:extension base="qdt:TimeReferenceCodeContentType"/>
+ </xs:simpleContent>
+ </xs:complexType>
+</xs:schema>
diff --git a/facturx/xsd/factur-x/Factur-X_BASIC_WL_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd b/facturx/xsd/factur-x/Factur-X_BASIC_WL_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
new file mode 100644
index 0000000..1ba7797
--- /dev/null
+++ b/facturx/xsd/factur-x/Factur-X_BASIC_WL_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:qdt="urn:un:unece:uncefact:data:standard:QualifiedDataType:100"
+ xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"
+ targetNamespace="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"
+ elementFormDefault="qualified"
+ version="100.D16B">
+ <xs:import namespace="urn:un:unece:uncefact:data:standard:QualifiedDataType:100" schemaLocation="Factur-X_BASIC_WL_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd"/>
+ <xs:import namespace="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100" schemaLocation="Factur-X_BASIC_WL_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd"/>
+ <xs:complexType name="CreditorFinancialAccountType">
+ <xs:sequence>
+ <xs:element name="IBANID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="ProprietaryID" type="udt:IDType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="DebtorFinancialAccountType">
+ <xs:sequence>
+ <xs:element name="IBANID" type="udt:IDType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="DocumentContextParameterType">
+ <xs:sequence>
+ <xs:element name="ID" type="udt:IDType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ExchangedDocumentContextType">
+ <xs:sequence>
+ <xs:element name="BusinessProcessSpecifiedDocumentContextParameter" type="ram:DocumentContextParameterType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="GuidelineSpecifiedDocumentContextParameter" type="ram:DocumentContextParameterType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ExchangedDocumentType">
+ <xs:sequence>
+ <xs:element name="ID" type="udt:IDType"/>
+ <xs:element name="TypeCode" type="qdt:DocumentCodeType" minOccurs="0"/>
+ <xs:element name="IssueDateTime" type="udt:DateTimeType"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="HeaderTradeAgreementType">
+ <xs:sequence>
+ <xs:element name="BuyerReference" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="SellerTradeParty" type="ram:TradePartyType" minOccurs="0"/>
+ <xs:element name="BuyerTradeParty" type="ram:TradePartyType" minOccurs="0"/>
+ <xs:element name="SellerTaxRepresentativeTradeParty" type="ram:TradePartyType" minOccurs="0"/>
+ <xs:element name="BuyerOrderReferencedDocument" type="ram:ReferencedDocumentType" minOccurs="0"/>
+ <xs:element name="ContractReferencedDocument" type="ram:ReferencedDocumentType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="HeaderTradeDeliveryType">
+ <xs:sequence>
+ <xs:element name="ActualDeliverySupplyChainEvent" type="ram:SupplyChainEventType" minOccurs="0"/>
+ <xs:element name="DespatchAdviceReferencedDocument" type="ram:ReferencedDocumentType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="HeaderTradeSettlementType">
+ <xs:sequence>
+ <xs:element name="CreditorReferenceID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="PaymentReference" type="udt:TextType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="InvoiceCurrencyCode" type="qdt:CurrencyCodeType" minOccurs="0"/>
+ <xs:element name="PayeeTradeParty" type="ram:TradePartyType" minOccurs="0"/>
+ <xs:element name="SpecifiedTradeSettlementPaymentMeans" type="ram:TradeSettlementPaymentMeansType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="ApplicableTradeTax" type="ram:TradeTaxType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="SpecifiedTradeAllowanceCharge" type="ram:TradeAllowanceChargeType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="SpecifiedTradePaymentTerms" type="ram:TradePaymentTermsType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="SpecifiedTradeSettlementHeaderMonetarySummation" type="ram:TradeSettlementHeaderMonetarySummationType" minOccurs="0"/>
+ <xs:element name="InvoiceReferencedDocument" type="ram:ReferencedDocumentType" minOccurs="0"/>
+ <xs:element name="ReceivableSpecifiedTradeAccountingAccount" type="ram:TradeAccountingAccountType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="LegalOrganizationType">
+ <xs:sequence>
+ <xs:element name="ID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="TradingBusinessName" type="udt:TextType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ReferencedDocumentType">
+ <xs:sequence>
+ <xs:element name="IssuerAssignedID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="FormattedIssueDateTime" type="qdt:FormattedDateTimeType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="SupplyChainEventType">
+ <xs:sequence>
+ <xs:element name="OccurrenceDateTime" type="udt:DateTimeType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="SupplyChainTradeTransactionType">
+ <xs:sequence>
+ <xs:element name="ApplicableHeaderTradeAgreement" type="ram:HeaderTradeAgreementType"/>
+ <xs:element name="ApplicableHeaderTradeDelivery" type="ram:HeaderTradeDeliveryType"/>
+ <xs:element name="ApplicableHeaderTradeSettlement" type="ram:HeaderTradeSettlementType"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TaxRegistrationType">
+ <xs:sequence>
+ <xs:element name="ID" type="udt:IDType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeAccountingAccountType">
+ <xs:sequence>
+ <xs:element name="ID" type="udt:IDType"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeAddressType">
+ <xs:sequence>
+ <xs:element name="PostcodeCode" type="udt:CodeType" minOccurs="0"/>
+ <xs:element name="LineOne" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="LineTwo" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="LineThree" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="CityName" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="CountryID" type="qdt:CountryIDType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeAllowanceChargeType">
+ <xs:sequence>
+ <xs:element name="ChargeIndicator" type="udt:IndicatorType" minOccurs="0"/>
+ <xs:element name="CalculationPercent" type="udt:PercentType" minOccurs="0"/>
+ <xs:element name="BasisAmount" type="udt:AmountType" minOccurs="0"/>
+ <xs:element name="ActualAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="ReasonCode" type="qdt:AllowanceChargeReasonCodeType" minOccurs="0"/>
+ <xs:element name="Reason" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="CategoryTradeTax" type="ram:TradeTaxType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeContactType">
+ <xs:sequence>
+ <xs:element name="PersonName" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="DepartmentName" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="TelephoneUniversalCommunication" type="ram:UniversalCommunicationType" minOccurs="0"/>
+ <xs:element name="FaxUniversalCommunication" type="ram:UniversalCommunicationType" minOccurs="0"/>
+ <xs:element name="EmailURIUniversalCommunication" type="ram:UniversalCommunicationType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradePartyType">
+ <xs:sequence>
+ <xs:element name="ID" type="udt:IDType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="GlobalID" type="udt:IDType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="Name" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="SpecifiedLegalOrganization" type="ram:LegalOrganizationType" minOccurs="0"/>
+ <xs:element name="DefinedTradeContact" type="ram:TradeContactType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="PostalTradeAddress" type="ram:TradeAddressType" minOccurs="0"/>
+ <xs:element name="URIUniversalCommunication" type="ram:UniversalCommunicationType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="SpecifiedTaxRegistration" type="ram:TaxRegistrationType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradePaymentTermsType">
+ <xs:sequence>
+ <xs:element name="DueDateDateTime" type="udt:DateTimeType" minOccurs="0"/>
+ <xs:element name="DirectDebitMandateID" type="udt:IDType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeSettlementHeaderMonetarySummationType">
+ <xs:sequence>
+ <xs:element name="LineTotalAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="ChargeTotalAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="AllowanceTotalAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="TaxBasisTotalAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="TaxTotalAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="GrandTotalAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="TotalPrepaidAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="DuePayableAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeSettlementPaymentMeansType">
+ <xs:sequence>
+ <xs:element name="TypeCode" type="qdt:PaymentMeansCodeType" minOccurs="0"/>
+ <xs:element name="PayerPartyDebtorFinancialAccount" type="ram:DebtorFinancialAccountType" minOccurs="0"/>
+ <xs:element name="PayeePartyCreditorFinancialAccount" type="ram:CreditorFinancialAccountType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeTaxType">
+ <xs:sequence>
+ <xs:element name="CalculatedAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="TypeCode" type="qdt:TaxTypeCodeType" minOccurs="0"/>
+ <xs:element name="ExemptionReason" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="BasisAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="CategoryCode" type="qdt:TaxCategoryCodeType" minOccurs="0"/>
+ <xs:element name="ExemptionReasonCode" type="udt:CodeType" minOccurs="0"/>
+ <xs:element name="DueDateTypeCode" type="qdt:TimeReferenceCodeType" minOccurs="0"/>
+ <xs:element name="RateApplicablePercent" type="udt:PercentType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="UniversalCommunicationType">
+ <xs:sequence>
+ <xs:element name="URIID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="CompleteNumber" type="udt:TextType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:schema>
diff --git a/facturx/xsd/factur-x/Factur-X_BASIC_WL_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd b/facturx/xsd/factur-x/Factur-X_BASIC_WL_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd
new file mode 100644
index 0000000..baa9c12
--- /dev/null
+++ b/facturx/xsd/factur-x/Factur-X_BASIC_WL_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ targetNamespace="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"
+ elementFormDefault="qualified"
+ version="100.D16B">
+ <xs:complexType name="AmountType">
+ <xs:simpleContent>
+ <xs:extension base="xs:decimal">
+ <xs:attribute name="currencyID" type="xs:token"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:complexType name="CodeType">
+ <xs:simpleContent>
+ <xs:extension base="xs:token"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:complexType name="DateTimeType">
+ <xs:choice>
+ <xs:element name="DateTimeString">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="format" type="xs:string"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:complexType>
+ <xs:complexType name="IDType">
+ <xs:simpleContent>
+ <xs:extension base="xs:token">
+ <xs:attribute name="schemeID" type="xs:token"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:complexType name="IndicatorType">
+ <xs:choice>
+ <xs:element name="Indicator" type="xs:boolean"/>
+ </xs:choice>
+ </xs:complexType>
+ <xs:complexType name="PercentType">
+ <xs:simpleContent>
+ <xs:extension base="xs:decimal"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:complexType name="TextType">
+ <xs:simpleContent>
+ <xs:extension base="xs:string"/>
+ </xs:simpleContent>
+ </xs:complexType>
+</xs:schema>
diff --git a/facturx/xsd/factur-x/Factur-X_EN16931.xsd b/facturx/xsd/factur-x/Factur-X_EN16931.xsd
new file mode 100644
index 0000000..3e79051
--- /dev/null
+++ b/facturx/xsd/factur-x/Factur-X_EN16931.xsd
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:qdt="urn:un:unece:uncefact:data:standard:QualifiedDataType:100"
+ xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"
+ xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"
+ targetNamespace="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100"
+ elementFormDefault="qualified">
+ <xs:import namespace="urn:un:unece:uncefact:data:standard:QualifiedDataType:100" schemaLocation="Factur-X_EN16931_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd"/>
+ <xs:import namespace="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100" schemaLocation="Factur-X_EN16931_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd"/>
+ <xs:import namespace="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100" schemaLocation="Factur-X_EN16931_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd"/>
+ <xs:element name="CrossIndustryInvoice" type="rsm:CrossIndustryInvoiceType"/>
+ <xs:complexType name="CrossIndustryInvoiceType">
+ <xs:sequence>
+ <xs:element name="ExchangedDocumentContext" type="ram:ExchangedDocumentContextType"/>
+ <xs:element name="ExchangedDocument" type="ram:ExchangedDocumentType"/>
+ <xs:element name="SupplyChainTradeTransaction" type="ram:SupplyChainTradeTransactionType"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:schema>
diff --git a/facturx/xsd/factur-x/Factur-X_EN16931_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd b/facturx/xsd/factur-x/Factur-X_EN16931_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd
new file mode 100644
index 0000000..09fa0d4
--- /dev/null
+++ b/facturx/xsd/factur-x/Factur-X_EN16931_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:qdt="urn:un:unece:uncefact:data:standard:QualifiedDataType:100"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"
+ targetNamespace="urn:un:unece:uncefact:data:standard:QualifiedDataType:100"
+ elementFormDefault="qualified"
+ version="100.D16B">
+ <xs:import namespace="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100" schemaLocation="Factur-X_EN16931_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd"/>
+ <xs:simpleType name="AllowanceChargeReasonCodeContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="AllowanceChargeReasonCodeType">
+ <xs:simpleContent>
+ <xs:extension base="qdt:AllowanceChargeReasonCodeContentType"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="CountryIDContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="CountryIDType">
+ <xs:simpleContent>
+ <xs:extension base="qdt:CountryIDContentType"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="CurrencyCodeContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="CurrencyCodeType">
+ <xs:simpleContent>
+ <xs:extension base="qdt:CurrencyCodeContentType"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="DocumentCodeContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="DocumentCodeType">
+ <xs:simpleContent>
+ <xs:extension base="qdt:DocumentCodeContentType"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="FormattedDateTimeFormatContentType">
+ <xs:restriction base="xs:string"/>
+ </xs:simpleType>
+ <xs:complexType name="FormattedDateTimeType">
+ <xs:sequence>
+ <xs:element name="DateTimeString">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="format" type="qdt:FormattedDateTimeFormatContentType"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="PaymentMeansCodeContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="PaymentMeansCodeType">
+ <xs:simpleContent>
+ <xs:extension base="qdt:PaymentMeansCodeContentType"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="ReferenceCodeContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="ReferenceCodeType">
+ <xs:simpleContent>
+ <xs:extension base="qdt:ReferenceCodeContentType"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="TaxCategoryCodeContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="TaxCategoryCodeType">
+ <xs:simpleContent>
+ <xs:extension base="qdt:TaxCategoryCodeContentType"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="TaxTypeCodeContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="TaxTypeCodeType">
+ <xs:simpleContent>
+ <xs:extension base="qdt:TaxTypeCodeContentType"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="TimeReferenceCodeContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="TimeReferenceCodeType">
+ <xs:simpleContent>
+ <xs:extension base="qdt:TimeReferenceCodeContentType"/>
+ </xs:simpleContent>
+ </xs:complexType>
+</xs:schema>
diff --git a/facturx/xsd/factur-x/Factur-X_EN16931_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd b/facturx/xsd/factur-x/Factur-X_EN16931_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
new file mode 100644
index 0000000..7db9240
--- /dev/null
+++ b/facturx/xsd/factur-x/Factur-X_EN16931_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
@@ -0,0 +1,320 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:qdt="urn:un:unece:uncefact:data:standard:QualifiedDataType:100"
+ xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"
+ targetNamespace="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"
+ elementFormDefault="qualified"
+ version="100.D16B">
+ <xs:import namespace="urn:un:unece:uncefact:data:standard:QualifiedDataType:100" schemaLocation="Factur-X_EN16931_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd"/>
+ <xs:import namespace="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100" schemaLocation="Factur-X_EN16931_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd"/>
+ <xs:complexType name="CreditorFinancialAccountType">
+ <xs:sequence>
+ <xs:element name="IBANID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="AccountName" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="ProprietaryID" type="udt:IDType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="CreditorFinancialInstitutionType">
+ <xs:sequence>
+ <xs:element name="BICID" type="udt:IDType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="DebtorFinancialAccountType">
+ <xs:sequence>
+ <xs:element name="IBANID" type="udt:IDType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="DocumentContextParameterType">
+ <xs:sequence>
+ <xs:element name="ID" type="udt:IDType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="DocumentLineDocumentType">
+ <xs:sequence>
+ <xs:element name="LineID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="IncludedNote" type="ram:NoteType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ExchangedDocumentContextType">
+ <xs:sequence>
+ <xs:element name="BusinessProcessSpecifiedDocumentContextParameter" type="ram:DocumentContextParameterType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="GuidelineSpecifiedDocumentContextParameter" type="ram:DocumentContextParameterType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ExchangedDocumentType">
+ <xs:sequence>
+ <xs:element name="ID" type="udt:IDType"/>
+ <xs:element name="TypeCode" type="qdt:DocumentCodeType" minOccurs="0"/>
+ <xs:element name="IssueDateTime" type="udt:DateTimeType"/>
+ <xs:element name="IncludedNote" type="ram:NoteType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="HeaderTradeAgreementType">
+ <xs:sequence>
+ <xs:element name="BuyerReference" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="SellerTradeParty" type="ram:TradePartyType" minOccurs="0"/>
+ <xs:element name="BuyerTradeParty" type="ram:TradePartyType" minOccurs="0"/>
+ <xs:element name="SellerTaxRepresentativeTradeParty" type="ram:TradePartyType" minOccurs="0"/>
+ <xs:element name="SellerOrderReferencedDocument" type="ram:ReferencedDocumentType" minOccurs="0"/>
+ <xs:element name="BuyerOrderReferencedDocument" type="ram:ReferencedDocumentType" minOccurs="0"/>
+ <xs:element name="ContractReferencedDocument" type="ram:ReferencedDocumentType" minOccurs="0"/>
+ <xs:element name="AdditionalReferencedDocument" type="ram:ReferencedDocumentType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="SpecifiedProcuringProject" type="ram:ProcuringProjectType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="HeaderTradeDeliveryType">
+ <xs:sequence>
+ <xs:element name="ShipToTradeParty" type="ram:TradePartyType" minOccurs="0"/>
+ <xs:element name="ActualDeliverySupplyChainEvent" type="ram:SupplyChainEventType" minOccurs="0"/>
+ <xs:element name="DespatchAdviceReferencedDocument" type="ram:ReferencedDocumentType" minOccurs="0"/>
+ <xs:element name="ReceivingAdviceReferencedDocument" type="ram:ReferencedDocumentType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="HeaderTradeSettlementType">
+ <xs:sequence>
+ <xs:element name="CreditorReferenceID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="PaymentReference" type="udt:TextType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="TaxCurrencyCode" type="qdt:CurrencyCodeType" minOccurs="0"/>
+ <xs:element name="InvoiceCurrencyCode" type="qdt:CurrencyCodeType" minOccurs="0"/>
+ <xs:element name="PayeeTradeParty" type="ram:TradePartyType" minOccurs="0"/>
+ <xs:element name="SpecifiedTradeSettlementPaymentMeans" type="ram:TradeSettlementPaymentMeansType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="ApplicableTradeTax" type="ram:TradeTaxType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="BillingSpecifiedPeriod" type="ram:SpecifiedPeriodType" minOccurs="0"/>
+ <xs:element name="SpecifiedTradeAllowanceCharge" type="ram:TradeAllowanceChargeType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="SpecifiedTradePaymentTerms" type="ram:TradePaymentTermsType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="SpecifiedTradeSettlementHeaderMonetarySummation" type="ram:TradeSettlementHeaderMonetarySummationType" minOccurs="0"/>
+ <xs:element name="InvoiceReferencedDocument" type="ram:ReferencedDocumentType" minOccurs="0"/>
+ <xs:element name="ReceivableSpecifiedTradeAccountingAccount" type="ram:TradeAccountingAccountType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="LegalOrganizationType">
+ <xs:sequence>
+ <xs:element name="ID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="TradingBusinessName" type="udt:TextType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="LineTradeAgreementType">
+ <xs:sequence>
+ <xs:element name="BuyerOrderReferencedDocument" type="ram:ReferencedDocumentType" minOccurs="0"/>
+ <xs:element name="GrossPriceProductTradePrice" type="ram:TradePriceType" minOccurs="0"/>
+ <xs:element name="NetPriceProductTradePrice" type="ram:TradePriceType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="LineTradeDeliveryType">
+ <xs:sequence>
+ <xs:element name="BilledQuantity" type="udt:QuantityType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="LineTradeSettlementType">
+ <xs:sequence>
+ <xs:element name="ApplicableTradeTax" type="ram:TradeTaxType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="BillingSpecifiedPeriod" type="ram:SpecifiedPeriodType" minOccurs="0"/>
+ <xs:element name="SpecifiedTradeAllowanceCharge" type="ram:TradeAllowanceChargeType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="SpecifiedTradeSettlementLineMonetarySummation" type="ram:TradeSettlementLineMonetarySummationType" minOccurs="0"/>
+ <xs:element name="AdditionalReferencedDocument" type="ram:ReferencedDocumentType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="ReceivableSpecifiedTradeAccountingAccount" type="ram:TradeAccountingAccountType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="NoteType">
+ <xs:sequence>
+ <xs:element name="Content" type="udt:TextType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="SubjectCode" type="udt:CodeType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ProcuringProjectType">
+ <xs:sequence>
+ <xs:element name="ID" type="udt:IDType"/>
+ <xs:element name="Name" type="udt:TextType"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ProductCharacteristicType">
+ <xs:sequence>
+ <xs:element name="Description" type="udt:TextType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="Value" type="udt:TextType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ProductClassificationType">
+ <xs:sequence>
+ <xs:element name="ClassCode" type="udt:CodeType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ReferencedDocumentType">
+ <xs:sequence>
+ <xs:element name="IssuerAssignedID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="URIID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="LineID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="TypeCode" type="qdt:DocumentCodeType" minOccurs="0"/>
+ <xs:element name="Name" type="udt:TextType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="AttachmentBinaryObject" type="udt:BinaryObjectType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="ReferenceTypeCode" type="qdt:ReferenceCodeType" minOccurs="0"/>
+ <xs:element name="FormattedIssueDateTime" type="qdt:FormattedDateTimeType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="SpecifiedPeriodType">
+ <xs:sequence>
+ <xs:element name="StartDateTime" type="udt:DateTimeType" minOccurs="0"/>
+ <xs:element name="EndDateTime" type="udt:DateTimeType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="SupplyChainEventType">
+ <xs:sequence>
+ <xs:element name="OccurrenceDateTime" type="udt:DateTimeType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="SupplyChainTradeLineItemType">
+ <xs:sequence>
+ <xs:element name="AssociatedDocumentLineDocument" type="ram:DocumentLineDocumentType"/>
+ <xs:element name="SpecifiedTradeProduct" type="ram:TradeProductType" minOccurs="0"/>
+ <xs:element name="SpecifiedLineTradeAgreement" type="ram:LineTradeAgreementType" minOccurs="0"/>
+ <xs:element name="SpecifiedLineTradeDelivery" type="ram:LineTradeDeliveryType" minOccurs="0"/>
+ <xs:element name="SpecifiedLineTradeSettlement" type="ram:LineTradeSettlementType"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="SupplyChainTradeTransactionType">
+ <xs:sequence>
+ <xs:element name="IncludedSupplyChainTradeLineItem" type="ram:SupplyChainTradeLineItemType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="ApplicableHeaderTradeAgreement" type="ram:HeaderTradeAgreementType"/>
+ <xs:element name="ApplicableHeaderTradeDelivery" type="ram:HeaderTradeDeliveryType"/>
+ <xs:element name="ApplicableHeaderTradeSettlement" type="ram:HeaderTradeSettlementType"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TaxRegistrationType">
+ <xs:sequence>
+ <xs:element name="ID" type="udt:IDType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeAccountingAccountType">
+ <xs:sequence>
+ <xs:element name="ID" type="udt:IDType"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeAddressType">
+ <xs:sequence>
+ <xs:element name="PostcodeCode" type="udt:CodeType" minOccurs="0"/>
+ <xs:element name="LineOne" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="LineTwo" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="LineThree" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="CityName" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="CountryID" type="qdt:CountryIDType" minOccurs="0"/>
+ <xs:element name="CountrySubDivisionName" type="udt:TextType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeAllowanceChargeType">
+ <xs:sequence>
+ <xs:element name="ChargeIndicator" type="udt:IndicatorType" minOccurs="0"/>
+ <xs:element name="CalculationPercent" type="udt:PercentType" minOccurs="0"/>
+ <xs:element name="BasisAmount" type="udt:AmountType" minOccurs="0"/>
+ <xs:element name="ActualAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="ReasonCode" type="qdt:AllowanceChargeReasonCodeType" minOccurs="0"/>
+ <xs:element name="Reason" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="CategoryTradeTax" type="ram:TradeTaxType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeContactType">
+ <xs:sequence>
+ <xs:element name="PersonName" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="DepartmentName" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="TelephoneUniversalCommunication" type="ram:UniversalCommunicationType" minOccurs="0"/>
+ <xs:element name="FaxUniversalCommunication" type="ram:UniversalCommunicationType" minOccurs="0"/>
+ <xs:element name="EmailURIUniversalCommunication" type="ram:UniversalCommunicationType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeCountryType">
+ <xs:sequence>
+ <xs:element name="ID" type="qdt:CountryIDType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradePartyType">
+ <xs:sequence>
+ <xs:element name="ID" type="udt:IDType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="GlobalID" type="udt:IDType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="Name" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="Description" type="udt:TextType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="SpecifiedLegalOrganization" type="ram:LegalOrganizationType" minOccurs="0"/>
+ <xs:element name="DefinedTradeContact" type="ram:TradeContactType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="PostalTradeAddress" type="ram:TradeAddressType" minOccurs="0"/>
+ <xs:element name="URIUniversalCommunication" type="ram:UniversalCommunicationType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="SpecifiedTaxRegistration" type="ram:TaxRegistrationType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradePaymentTermsType">
+ <xs:sequence>
+ <xs:element name="Description" type="udt:TextType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="DueDateDateTime" type="udt:DateTimeType" minOccurs="0"/>
+ <xs:element name="DirectDebitMandateID" type="udt:IDType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradePriceType">
+ <xs:sequence>
+ <xs:element name="ChargeAmount" type="udt:AmountType" maxOccurs="unbounded"/>
+ <xs:element name="BasisQuantity" type="udt:QuantityType" minOccurs="0"/>
+ <xs:element name="AppliedTradeAllowanceCharge" type="ram:TradeAllowanceChargeType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeProductType">
+ <xs:sequence>
+ <xs:element name="GlobalID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="SellerAssignedID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="BuyerAssignedID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="Name" type="udt:TextType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="Description" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="ApplicableProductCharacteristic" type="ram:ProductCharacteristicType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="DesignatedProductClassification" type="ram:ProductClassificationType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="OriginTradeCountry" type="ram:TradeCountryType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeSettlementFinancialCardType">
+ <xs:sequence>
+ <xs:element name="ID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="CardholderName" type="udt:TextType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeSettlementHeaderMonetarySummationType">
+ <xs:sequence>
+ <xs:element name="LineTotalAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="ChargeTotalAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="AllowanceTotalAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="TaxBasisTotalAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="TaxTotalAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="RoundingAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="GrandTotalAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="TotalPrepaidAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="DuePayableAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeSettlementLineMonetarySummationType">
+ <xs:sequence>
+ <xs:element name="LineTotalAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeSettlementPaymentMeansType">
+ <xs:sequence>
+ <xs:element name="TypeCode" type="qdt:PaymentMeansCodeType" minOccurs="0"/>
+ <xs:element name="Information" type="udt:TextType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="ApplicableTradeSettlementFinancialCard" type="ram:TradeSettlementFinancialCardType" minOccurs="0"/>
+ <xs:element name="PayerPartyDebtorFinancialAccount" type="ram:DebtorFinancialAccountType" minOccurs="0"/>
+ <xs:element name="PayeePartyCreditorFinancialAccount" type="ram:CreditorFinancialAccountType" minOccurs="0"/>
+ <xs:element name="PayeeSpecifiedCreditorFinancialInstitution" type="ram:CreditorFinancialInstitutionType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeTaxType">
+ <xs:sequence>
+ <xs:element name="CalculatedAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="TypeCode" type="qdt:TaxTypeCodeType" minOccurs="0"/>
+ <xs:element name="ExemptionReason" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="BasisAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="CategoryCode" type="qdt:TaxCategoryCodeType" minOccurs="0"/>
+ <xs:element name="ExemptionReasonCode" type="udt:CodeType" minOccurs="0"/>
+ <xs:element name="TaxPointDate" type="udt:DateType" minOccurs="0"/>
+ <xs:element name="DueDateTypeCode" type="qdt:TimeReferenceCodeType" minOccurs="0"/>
+ <xs:element name="RateApplicablePercent" type="udt:PercentType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="UniversalCommunicationType">
+ <xs:sequence>
+ <xs:element name="URIID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="CompleteNumber" type="udt:TextType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:schema>
diff --git a/facturx/xsd/factur-x/Factur-X_EN16931_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd b/facturx/xsd/factur-x/Factur-X_EN16931_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd
new file mode 100644
index 0000000..5a20d87
--- /dev/null
+++ b/facturx/xsd/factur-x/Factur-X_EN16931_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ targetNamespace="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"
+ elementFormDefault="qualified"
+ version="100.D16B">
+ <xs:complexType name="AmountType">
+ <xs:simpleContent>
+ <xs:extension base="xs:decimal">
+ <xs:attribute name="currencyID" type="xs:token"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:complexType name="BinaryObjectType">
+ <xs:simpleContent>
+ <xs:extension base="xs:base64Binary">
+ <xs:attribute name="mimeCode" type="xs:token"/>
+ <xs:attribute name="filename" type="xs:string"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:complexType name="CodeType">
+ <xs:simpleContent>
+ <xs:extension base="xs:token">
+ <xs:attribute name="listID" type="xs:token"/>
+ <xs:attribute name="listVersionID" type="xs:token"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:complexType name="DateTimeType">
+ <xs:choice>
+ <xs:element name="DateTimeString">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="format" type="xs:string"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:complexType>
+ <xs:complexType name="DateType">
+ <xs:choice>
+ <xs:element name="DateString">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="format" type="xs:string"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:complexType>
+ <xs:complexType name="IDType">
+ <xs:simpleContent>
+ <xs:extension base="xs:token">
+ <xs:attribute name="schemeID" type="xs:token"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:complexType name="IndicatorType">
+ <xs:choice>
+ <xs:element name="Indicator" type="xs:boolean"/>
+ </xs:choice>
+ </xs:complexType>
+ <xs:complexType name="PercentType">
+ <xs:simpleContent>
+ <xs:extension base="xs:decimal"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:complexType name="QuantityType">
+ <xs:simpleContent>
+ <xs:extension base="xs:decimal">
+ <xs:attribute name="unitCode" type="xs:token"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:complexType name="TextType">
+ <xs:simpleContent>
+ <xs:extension base="xs:string"/>
+ </xs:simpleContent>
+ </xs:complexType>
+</xs:schema>
diff --git a/facturx/xsd/zugferd/ZUGFeRD1p0.xsd b/facturx/xsd/zugferd/ZUGFeRD1p0.xsd
new file mode 100644
index 0000000..cc3075a
--- /dev/null
+++ b/facturx/xsd/zugferd/ZUGFeRD1p0.xsd
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:rsm="urn:ferd:CrossIndustryDocument:invoice:1p0"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:qdt="urn:un:unece:uncefact:data:standard:QualifiedDataType:12"
+ xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:12"
+ xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:15"
+ targetNamespace="urn:ferd:CrossIndustryDocument:invoice:1p0"
+ elementFormDefault="qualified">
+ <xs:import namespace="urn:un:unece:uncefact:data:standard:QualifiedDataType:12" schemaLocation="ZUGFeRD1p0_urn_un_unece_uncefact_data_standard_QualifiedDataType_12.xsd"/>
+ <xs:import namespace="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:12" schemaLocation="ZUGFeRD1p0_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_12.xsd"/>
+ <xs:import namespace="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:15" schemaLocation="ZUGFeRD1p0_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_15.xsd"/>
+ <xs:element name="CrossIndustryDocument" type="rsm:CrossIndustryDocumentType"/>
+ <xs:complexType name="CrossIndustryDocumentType">
+ <xs:sequence>
+ <xs:element name="SpecifiedExchangedDocumentContext" type="ram:ExchangedDocumentContextType"/>
+ <xs:element name="HeaderExchangedDocument" type="ram:ExchangedDocumentType"/>
+ <xs:element name="SpecifiedSupplyChainTradeTransaction" type="ram:SupplyChainTradeTransactionType"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:schema>
diff --git a/facturx/xsd/zugferd/ZUGFeRD1p0_urn_un_unece_uncefact_data_standard_QualifiedDataType_12.xsd b/facturx/xsd/zugferd/ZUGFeRD1p0_urn_un_unece_uncefact_data_standard_QualifiedDataType_12.xsd
new file mode 100644
index 0000000..42b66e8
--- /dev/null
+++ b/facturx/xsd/zugferd/ZUGFeRD1p0_urn_un_unece_uncefact_data_standard_QualifiedDataType_12.xsd
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:qdt="urn:un:unece:uncefact:data:standard:QualifiedDataType:12"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:15"
+ targetNamespace="urn:un:unece:uncefact:data:standard:QualifiedDataType:12"
+ elementFormDefault="qualified"
+ version="12.0">
+ <xs:import namespace="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:15" schemaLocation="ZUGFeRD1p0_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_15.xsd"/>
+ <xs:simpleType name="AllowanceChargeReasonCodeContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="AllowanceChargeReasonCodeType">
+ <xs:simpleContent>
+ <xs:extension base="qdt:AllowanceChargeReasonCodeContentType"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="CountryIDContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="CountryIDType">
+ <xs:simpleContent>
+ <xs:extension base="qdt:CountryIDContentType"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="DateMandatoryDateTimeType">
+ <xs:union memberTypes="xs:dateTime xs:date"/>
+ </xs:simpleType>
+ <xs:simpleType name="DeliveryTermsCodeContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="DeliveryTermsCodeType">
+ <xs:simpleContent>
+ <xs:extension base="qdt:DeliveryTermsCodeContentType"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="DocumentCodeContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="DocumentCodeType">
+ <xs:simpleContent>
+ <xs:extension base="qdt:DocumentCodeContentType"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="PaymentMeansCodeContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="PaymentMeansCodeType">
+ <xs:simpleContent>
+ <xs:extension base="qdt:PaymentMeansCodeContentType"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="ReferenceCodeContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="ReferenceCodeType">
+ <xs:simpleContent>
+ <xs:extension base="qdt:ReferenceCodeContentType"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="TaxCategoryCodeContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="TaxCategoryCodeType">
+ <xs:simpleContent>
+ <xs:extension base="qdt:TaxCategoryCodeContentType"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="TaxTypeCodeContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="TaxTypeCodeType">
+ <xs:simpleContent>
+ <xs:extension base="qdt:TaxTypeCodeContentType"/>
+ </xs:simpleContent>
+ </xs:complexType>
+</xs:schema>
diff --git a/facturx/xsd/zugferd/ZUGFeRD1p0_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_12.xsd b/facturx/xsd/zugferd/ZUGFeRD1p0_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_12.xsd
new file mode 100644
index 0000000..d207ef0
--- /dev/null
+++ b/facturx/xsd/zugferd/ZUGFeRD1p0_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_12.xsd
@@ -0,0 +1,352 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:12"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:qdt="urn:un:unece:uncefact:data:standard:QualifiedDataType:12"
+ xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:15"
+ targetNamespace="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:12"
+ elementFormDefault="qualified"
+ version="12.0">
+ <xs:import namespace="urn:un:unece:uncefact:data:standard:QualifiedDataType:12" schemaLocation="ZUGFeRD1p0_urn_un_unece_uncefact_data_standard_QualifiedDataType_12.xsd"/>
+ <xs:import namespace="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:15" schemaLocation="ZUGFeRD1p0_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_15.xsd"/>
+ <xs:complexType name="CreditorFinancialAccountType">
+ <xs:sequence>
+ <xs:element name="IBANID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="AccountName" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="ProprietaryID" type="udt:IDType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="CreditorFinancialInstitutionType">
+ <xs:sequence>
+ <xs:element name="BICID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="GermanBankleitzahlID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="Name" type="udt:TextType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="DebtorFinancialAccountType">
+ <xs:sequence>
+ <xs:element name="IBANID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="ProprietaryID" type="udt:IDType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="DebtorFinancialInstitutionType">
+ <xs:sequence>
+ <xs:element name="BICID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="GermanBankleitzahlID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="Name" type="udt:TextType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="DocumentContextParameterType">
+ <xs:sequence>
+ <xs:element name="ID" type="udt:IDType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="DocumentLineDocumentType">
+ <xs:sequence>
+ <xs:element name="LineID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="IncludedNote" type="ram:NoteType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ExchangedDocumentContextType">
+ <xs:sequence>
+ <xs:element name="TestIndicator" type="udt:IndicatorType" minOccurs="0"/>
+ <xs:element name="BusinessProcessSpecifiedDocumentContextParameter" type="ram:DocumentContextParameterType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="GuidelineSpecifiedDocumentContextParameter" type="ram:DocumentContextParameterType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ExchangedDocumentType">
+ <xs:sequence>
+ <xs:element name="ID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="Name" type="udt:TextType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="TypeCode" type="qdt:DocumentCodeType" minOccurs="0"/>
+ <xs:element name="IssueDateTime" type="udt:DateTimeType" minOccurs="0"/>
+ <xs:element name="CopyIndicator" type="udt:IndicatorType" minOccurs="0"/>
+ <xs:element name="LanguageID" type="udt:IDType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="IncludedNote" type="ram:NoteType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="EffectiveSpecifiedPeriod" type="ram:SpecifiedPeriodType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="LogisticsServiceChargeType">
+ <xs:sequence>
+ <xs:element name="Description" type="udt:TextType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="AppliedAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="AppliedTradeTax" type="ram:TradeTaxType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="LogisticsTransportMovementType">
+ <xs:sequence>
+ <xs:element name="ModeCode" type="udt:CodeType" minOccurs="0"/>
+ <xs:element name="ID" type="udt:IDType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="NoteType">
+ <xs:sequence>
+ <xs:element name="ContentCode" type="udt:CodeType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="Content" type="udt:TextType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="SubjectCode" type="udt:CodeType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ProductCharacteristicType">
+ <xs:sequence>
+ <xs:element name="TypeCode" type="udt:CodeType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="Description" type="udt:TextType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="ValueMeasure" type="udt:MeasureType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="Value" type="udt:TextType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ProductClassificationType">
+ <xs:sequence>
+ <xs:element name="ClassCode" type="udt:CodeType" minOccurs="0"/>
+ <xs:element name="ClassName" type="udt:TextType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ReferencedDocumentType">
+ <xs:sequence>
+ <xs:element name="IssueDateTime" type="qdt:DateMandatoryDateTimeType" minOccurs="0"/>
+ <xs:element name="LineID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="TypeCode" type="qdt:DocumentCodeType" minOccurs="0"/>
+ <xs:element name="ID" type="udt:IDType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="ReferenceTypeCode" type="qdt:ReferenceCodeType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ReferencedProductType">
+ <xs:sequence>
+ <xs:element name="GlobalID" type="udt:IDType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="SellerAssignedID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="BuyerAssignedID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="Name" type="udt:TextType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="Description" type="udt:TextType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="UnitQuantity" type="udt:QuantityType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="SpecifiedPeriodType">
+ <xs:sequence>
+ <xs:element name="StartDateTime" type="udt:DateTimeType" minOccurs="0"/>
+ <xs:element name="EndDateTime" type="udt:DateTimeType" minOccurs="0"/>
+ <xs:element name="CompleteDateTime" type="udt:DateTimeType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="SupplyChainConsignmentType">
+ <xs:sequence>
+ <xs:element name="SpecifiedLogisticsTransportMovement" type="ram:LogisticsTransportMovementType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="SupplyChainEventType">
+ <xs:sequence>
+ <xs:element name="OccurrenceDateTime" type="udt:DateTimeType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="SupplyChainTradeAgreementType">
+ <xs:sequence>
+ <xs:element name="BuyerReference" type="udt:TextType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="SellerTradeParty" type="ram:TradePartyType" minOccurs="0"/>
+ <xs:element name="BuyerTradeParty" type="ram:TradePartyType" minOccurs="0"/>
+ <xs:element name="ProductEndUserTradeParty" type="ram:TradePartyType" minOccurs="0"/>
+ <xs:element name="ApplicableTradeDeliveryTerms" type="ram:TradeDeliveryTermsType" minOccurs="0"/>
+ <xs:element name="BuyerOrderReferencedDocument" type="ram:ReferencedDocumentType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="ContractReferencedDocument" type="ram:ReferencedDocumentType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="AdditionalReferencedDocument" type="ram:ReferencedDocumentType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="GrossPriceProductTradePrice" type="ram:TradePriceType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="NetPriceProductTradePrice" type="ram:TradePriceType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="CustomerOrderReferencedDocument" type="ram:ReferencedDocumentType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="SupplyChainTradeDeliveryType">
+ <xs:sequence>
+ <xs:element name="BilledQuantity" type="udt:QuantityType" minOccurs="0"/>
+ <xs:element name="ChargeFreeQuantity" type="udt:QuantityType" minOccurs="0"/>
+ <xs:element name="PackageQuantity" type="udt:QuantityType" minOccurs="0"/>
+ <xs:element name="RelatedSupplyChainConsignment" type="ram:SupplyChainConsignmentType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="ShipToTradeParty" type="ram:TradePartyType" minOccurs="0"/>
+ <xs:element name="UltimateShipToTradeParty" type="ram:TradePartyType" minOccurs="0"/>
+ <xs:element name="ShipFromTradeParty" type="ram:TradePartyType" minOccurs="0"/>
+ <xs:element name="ActualDeliverySupplyChainEvent" type="ram:SupplyChainEventType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="DespatchAdviceReferencedDocument" type="ram:ReferencedDocumentType" minOccurs="0"/>
+ <xs:element name="ReceivingAdviceReferencedDocument" type="ram:ReferencedDocumentType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="DeliveryNoteReferencedDocument" type="ram:ReferencedDocumentType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="SupplyChainTradeLineItemType">
+ <xs:sequence>
+ <xs:element name="AssociatedDocumentLineDocument" type="ram:DocumentLineDocumentType" minOccurs="0"/>
+ <xs:element name="SpecifiedSupplyChainTradeAgreement" type="ram:SupplyChainTradeAgreementType" minOccurs="0"/>
+ <xs:element name="SpecifiedSupplyChainTradeDelivery" type="ram:SupplyChainTradeDeliveryType" minOccurs="0"/>
+ <xs:element name="SpecifiedSupplyChainTradeSettlement" type="ram:SupplyChainTradeSettlementType" minOccurs="0"/>
+ <xs:element name="SpecifiedTradeProduct" type="ram:TradeProductType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="SupplyChainTradeSettlementType">
+ <xs:sequence>
+ <xs:element name="PaymentReference" type="udt:TextType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="InvoiceCurrencyCode" type="udt:CodeType" minOccurs="0"/>
+ <xs:element name="InvoiceeTradeParty" type="ram:TradePartyType" minOccurs="0"/>
+ <xs:element name="PayeeTradeParty" type="ram:TradePartyType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="SpecifiedTradeSettlementPaymentMeans" type="ram:TradeSettlementPaymentMeansType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="ApplicableTradeTax" type="ram:TradeTaxType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="BillingSpecifiedPeriod" type="ram:SpecifiedPeriodType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="SpecifiedTradeAllowanceCharge" type="ram:TradeAllowanceChargeType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="SpecifiedLogisticsServiceCharge" type="ram:LogisticsServiceChargeType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="SpecifiedTradePaymentTerms" type="ram:TradePaymentTermsType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="SpecifiedTradeAccountingAccount" type="ram:TradeAccountingAccountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="SpecifiedTradeSettlementMonetarySummation" type="ram:TradeSettlementMonetarySummationType" minOccurs="0"/>
+ <xs:element name="ReceivableSpecifiedTradeAccountingAccount" type="ram:TradeAccountingAccountType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="SupplyChainTradeTransactionType">
+ <xs:sequence>
+ <xs:element name="ApplicableSupplyChainTradeAgreement" type="ram:SupplyChainTradeAgreementType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="ApplicableSupplyChainTradeDelivery" type="ram:SupplyChainTradeDeliveryType" minOccurs="0"/>
+ <xs:element name="ApplicableSupplyChainTradeSettlement" type="ram:SupplyChainTradeSettlementType" minOccurs="0"/>
+ <xs:element name="IncludedSupplyChainTradeLineItem" type="ram:SupplyChainTradeLineItemType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TaxRegistrationType">
+ <xs:sequence>
+ <xs:element name="ID" type="udt:IDType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeAccountingAccountType">
+ <xs:sequence>
+ <xs:element name="ID" type="udt:IDType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeAddressType">
+ <xs:sequence>
+ <xs:element name="PostcodeCode" type="udt:CodeType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="LineOne" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="LineTwo" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="CityName" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="CountryID" type="qdt:CountryIDType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeAllowanceChargeType">
+ <xs:sequence>
+ <xs:element name="ChargeIndicator" type="udt:IndicatorType" minOccurs="0"/>
+ <xs:element name="SequenceNumeric" type="udt:NumericType" minOccurs="0"/>
+ <xs:element name="CalculationPercent" type="udt:PercentType" minOccurs="0"/>
+ <xs:element name="BasisAmount" type="udt:AmountType" minOccurs="0"/>
+ <xs:element name="BasisQuantity" type="udt:QuantityType" minOccurs="0"/>
+ <xs:element name="ActualAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="ReasonCode" type="qdt:AllowanceChargeReasonCodeType" minOccurs="0"/>
+ <xs:element name="Reason" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="CategoryTradeTax" type="ram:TradeTaxType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeContactType">
+ <xs:sequence>
+ <xs:element name="PersonName" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="DepartmentName" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="TelephoneUniversalCommunication" type="ram:UniversalCommunicationType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="FaxUniversalCommunication" type="ram:UniversalCommunicationType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="EmailURIUniversalCommunication" type="ram:UniversalCommunicationType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeCountryType">
+ <xs:sequence>
+ <xs:element name="ID" type="qdt:CountryIDType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeDeliveryTermsType">
+ <xs:sequence>
+ <xs:element name="DeliveryTypeCode" type="qdt:DeliveryTermsCodeType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradePartyType">
+ <xs:sequence>
+ <xs:element name="ID" type="udt:IDType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="GlobalID" type="udt:IDType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="Name" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="DefinedTradeContact" type="ram:TradeContactType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="PostalTradeAddress" type="ram:TradeAddressType" minOccurs="0"/>
+ <xs:element name="SpecifiedTaxRegistration" type="ram:TaxRegistrationType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradePaymentDiscountTermsType">
+ <xs:sequence>
+ <xs:element name="BasisDateTime" type="udt:DateTimeType" minOccurs="0"/>
+ <xs:element name="BasisPeriodMeasure" type="udt:MeasureType" minOccurs="0"/>
+ <xs:element name="BasisAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="CalculationPercent" type="udt:PercentType" minOccurs="0"/>
+ <xs:element name="ActualDiscountAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradePaymentPenaltyTermsType">
+ <xs:sequence>
+ <xs:element name="BasisDateTime" type="udt:DateTimeType" minOccurs="0"/>
+ <xs:element name="BasisPeriodMeasure" type="udt:MeasureType" minOccurs="0"/>
+ <xs:element name="BasisAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="CalculationPercent" type="udt:PercentType" minOccurs="0"/>
+ <xs:element name="ActualPenaltyAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradePaymentTermsType">
+ <xs:sequence>
+ <xs:element name="Description" type="udt:TextType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="DueDateDateTime" type="udt:DateTimeType" minOccurs="0"/>
+ <xs:element name="PartialPaymentAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="ApplicableTradePaymentPenaltyTerms" type="ram:TradePaymentPenaltyTermsType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="ApplicableTradePaymentDiscountTerms" type="ram:TradePaymentDiscountTermsType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradePriceType">
+ <xs:sequence>
+ <xs:element name="ChargeAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="BasisQuantity" type="udt:QuantityType" minOccurs="0"/>
+ <xs:element name="AppliedTradeAllowanceCharge" type="ram:TradeAllowanceChargeType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeProductType">
+ <xs:sequence>
+ <xs:element name="GlobalID" type="udt:IDType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="SellerAssignedID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="BuyerAssignedID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="Name" type="udt:TextType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="Description" type="udt:TextType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="ApplicableProductCharacteristic" type="ram:ProductCharacteristicType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="DesignatedProductClassification" type="ram:ProductClassificationType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="OriginTradeCountry" type="ram:TradeCountryType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="IncludedReferencedProduct" type="ram:ReferencedProductType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeSettlementMonetarySummationType">
+ <xs:sequence>
+ <xs:element name="LineTotalAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="ChargeTotalAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="AllowanceTotalAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="TaxBasisTotalAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="TaxTotalAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="GrandTotalAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="TotalPrepaidAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="TotalAllowanceChargeAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="DuePayableAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeSettlementPaymentMeansType">
+ <xs:sequence>
+ <xs:element name="TypeCode" type="qdt:PaymentMeansCodeType" minOccurs="0"/>
+ <xs:element name="Information" type="udt:TextType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="ID" type="udt:IDType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="PayerPartyDebtorFinancialAccount" type="ram:DebtorFinancialAccountType" minOccurs="0"/>
+ <xs:element name="PayeePartyCreditorFinancialAccount" type="ram:CreditorFinancialAccountType" minOccurs="0"/>
+ <xs:element name="PayerSpecifiedDebtorFinancialInstitution" type="ram:DebtorFinancialInstitutionType" minOccurs="0"/>
+ <xs:element name="PayeeSpecifiedCreditorFinancialInstitution" type="ram:CreditorFinancialInstitutionType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TradeTaxType">
+ <xs:sequence>
+ <xs:element name="CalculatedAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="TypeCode" type="qdt:TaxTypeCodeType" minOccurs="0"/>
+ <xs:element name="ExemptionReason" type="udt:TextType" minOccurs="0"/>
+ <xs:element name="BasisAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="LineTotalBasisAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="AllowanceChargeBasisAmount" type="udt:AmountType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="CategoryCode" type="qdt:TaxCategoryCodeType" minOccurs="0"/>
+ <xs:element name="ApplicablePercent" type="udt:PercentType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="UniversalCommunicationType">
+ <xs:sequence>
+ <xs:element name="URIID" type="udt:IDType" minOccurs="0"/>
+ <xs:element name="CompleteNumber" type="udt:TextType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:schema>
diff --git a/facturx/xsd/zugferd/ZUGFeRD1p0_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_15.xsd b/facturx/xsd/zugferd/ZUGFeRD1p0_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_15.xsd
new file mode 100644
index 0000000..4967014
--- /dev/null
+++ b/facturx/xsd/zugferd/ZUGFeRD1p0_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_15.xsd
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:15"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ targetNamespace="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:15"
+ elementFormDefault="qualified"
+ version="15.0">
+ <xs:complexType name="AmountType">
+ <xs:simpleContent>
+ <xs:extension base="xs:decimal">
+ <xs:attribute name="currencyID" type="udt:AmountTypeCurrencyIDContentType"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="AmountTypeCurrencyIDContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="CodeType">
+ <xs:simpleContent>
+ <xs:extension base="xs:token">
+ <xs:attribute name="listID" type="xs:token"/>
+ <xs:attribute name="listVersionID" type="xs:token"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:complexType name="DateTimeType">
+ <xs:choice>
+ <xs:element name="DateTimeString">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="format" type="xs:string"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:complexType>
+ <xs:complexType name="IDType">
+ <xs:simpleContent>
+ <xs:extension base="xs:token">
+ <xs:attribute name="schemeID" type="xs:token"/>
+ <xs:attribute name="schemeAgencyID" type="udt:IDTypeSchemeAgencyIDContentType"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="IDTypeSchemeAgencyIDContentType">
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:complexType name="IndicatorType">
+ <xs:choice>
+ <xs:element name="Indicator" type="xs:boolean"/>
+ </xs:choice>
+ </xs:complexType>
+ <xs:complexType name="MeasureType">
+ <xs:simpleContent>
+ <xs:extension base="xs:decimal">
+ <xs:attribute name="unitCode" type="udt:MeasureTypeUnitCodeContentType"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="MeasureTypeUnitCodeContentType">
+ <xs:restriction base="xs:token">
+ <xs:minLength value="1"/>
+ <xs:maxLength value="3"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="NumericType">
+ <xs:simpleContent>
+ <xs:extension base="xs:decimal"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:complexType name="PercentType">
+ <xs:simpleContent>
+ <xs:extension base="xs:decimal"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:complexType name="QuantityType">
+ <xs:simpleContent>
+ <xs:extension base="xs:decimal">
+ <xs:attribute name="unitCode" type="udt:QuantityTypeUnitCodeContentType"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="QuantityTypeUnitCodeContentType">
+ <xs:restriction base="xs:token">
+ <xs:minLength value="1"/>
+ <xs:maxLength value="3"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="TextType">
+ <xs:simpleContent>
+ <xs:extension base="xs:string"/>
+ </xs:simpleContent>
+ </xs:complexType>
+</xs:schema>
diff --git a/requirement.txt b/requirement.txt
new file mode 100644
index 0000000..79b8b25
--- /dev/null
+++ b/requirement.txt
@@ -0,0 +1,2 @@
+PyPDF2
+lxml
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..9ea92bc
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,32 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from setuptools import setup, find_packages
+
+setup(
+ name='factur-x',
+ version='0.1',
+ author='Alexis de Lattre',
+ author_email='alexis.delattre@akretion.com',
+ url='https://github.com/akretion/factur-x',
+ description='Factur-X: electronic invoicing standard for Germany & France',
+ long_description=open('README.rst').read(),
+ license='BSD',
+ classifiers=[
+ 'Development Status :: 4 - Beta',
+ 'Intended Audience :: Developers',
+ 'Programming Language :: Python :: 2.7',
+ 'License :: OSI Approved :: BSD License',
+ "Operating System :: OS Independent",
+ ],
+ keywords='e-invoice ZUGFeRD Factur-X Chorus',
+ packages=find_packages(),
+ install_requires=[r.strip() for r in
+ open('requirement.txt').read().splitlines()],
+ include_package_data=True,
+ scripts=[
+ 'bin/facturx-pdfgen',
+ 'bin/facturx-pdfextractxml',
+ 'bin/facturx-xmlcheck'],
+ zip_safe=False,
+)