from drafthorse.models.document import Document, IncludedNote
from drafthorse.utils import prettify
+"""
doc = Document()
doc.context.guideline_parameter.id = "urn:ferd:CrossIndustryDocument:invoice:1p0:comfort"
doc.header.id = "RE1337"
doc.header.notes.add(n)
doc.trade.agreement.seller.name = "Lieferant GmbH"
-
-print(prettify(doc.serialize()))
+"""
samplexml = open("sample.xml", "rb").read()
doc = Document.parse(samplexml)
-
-print(doc.header.name)
-print(doc.trade.agreement.seller.name)
-print([str(a.content) for a in doc.header.notes.children])
\ No newline at end of file
+print(prettify(doc.serialize()))
tag = "ApplicableTradeTax"
-class ApplicableTradeTax(LineApplicableTradeTax):
+class ApplicableTradeTax(Element):
+ calculated_amount = CurrencyField(NS_RAM, "CalculatedAmount", required=True,
+ profile=BASIC, _d="Steuerbetrag")
+ type_code = StringField(NS_RAM, "TypeCode", required=True, profile=BASIC,
+ _d="Steuerart (Code)")
+ exemption_reason = StringField(NS_RAM, "ExemptionReason", required=False,
+ profile=COMFORT, _d="Grund der Steuerbefreiung (Freitext)")
basis_amount = CurrencyField(NS_RAM, "BasisAmount", required=True,
profile=BASIC, _d="Basisbetrag der Steuerberechnung")
line_total_basis_amount = CurrencyField(NS_RAM, "LineTotalBasisAmount",
allowance_charge_basis_amount = CurrencyField(NS_RAM, "AllowanceChargeBasisAmount",
required=False, profile=EXTENDED,
_d="Gesamtbetrag Zu- und Abschläge des Steuersatzes")
+ category_code = StringField(NS_RAM, "CategoryCode", required=False,
+ profile=COMFORT, _d="Steuerkategorie (Wert)")
+ applicable_percent = DecimalField(NS_RAM, "ApplicablePercent",
+ required=True, profile=BASIC)
class Meta:
namespace = NS_RAM
class Meta:
namespace = NS_RAM
- tag = "BusinessSpecifiedDocumentContextParameter"
+ tag = "BusinessProcessSpecifiedDocumentContextParameter"
class DocumentContext(Element):
test_indicator = IndicatorField(NS_RAM, "TestIndicator", required=False,
profile=BASIC, _d="Testkennzeichen")
- guideline_parameter = Field(GuidelineDocumentContextParameter, required=True,
- profile=BASIC, _d="Anwendungsempfehlung")
business_parameter = Field(BusinessDocumentContextParameter, required=False,
profile=EXTENDED, _d="Geschäftsprozess, Wert")
+ guideline_parameter = Field(GuidelineDocumentContextParameter, required=True,
+ profile=BASIC, _d="Anwendungsempfehlung")
class Meta:
namespace = NS_FERD_1p0
def to_etree(self):
node = self._etree_node()
- for v in self._data.values():
+ for k, v in self._data.items():
if v is not None:
v.append_to(node)
return node
def get_tag(self):
return "{%s}%s" % (self.Meta.namespace, self.Meta.tag)
- def append_to(self, node):
- node.append(self.to_etree())
+ def append_to(self, node, required=False):
+ el = self.to_etree()
+ if required or list(el) or el.text:
+ node.append(el)
def serialize(self):
xml = b"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + ET.tostring(self.to_etree(), "utf-8")
- validate_xml(xmlout=xml, schema="ZUGFeRD1p0")
- return xml
+ return validate_xml(xmlout=xml, schema="ZUGFeRD1p0")
def from_etree(self, root):
if hasattr(self, 'Meta') and hasattr(self.Meta, 'namespace') and root.tag != "{%s}%s" % (self.Meta.namespace, self.Meta.tag):
class DecimalElement(StringElement):
- def __init__(self, namespace, tag, value=0):
+ def __init__(self, namespace, tag, value=None):
super().__init__(namespace, tag)
self.value = value
def to_etree(self):
node = self._etree_node()
- node.text = str(self.value)
+ node.text = str(self.value) if self.value is not None else ""
return node
def __str__(self):
class IndicatorElement(StringElement):
- def __init__(self, namespace, tag, value=None):
+ def __init__(self, namespace, tag, value=False):
super().__init__(namespace, tag)
self.value = value
def to_etree(self):
t = self._etree_node()
node = ET.Element("{%s}%s" % (NS_UDT, "Indicator"))
- node.text = self.value
+ node.text = str(self.value).lower()
t.append(node)
+ return t
def __str__(self):
return "{}".format(self.value)
class TradeProduct(Element):
- name = StringField(NS_RAM, "Name", required=False, profile=COMFORT)
- description = StringField(NS_RAM, "Description", required=False, profile=COMFORT)
global_id = IDField(NS_RAM, "GlobalID", required=False, profile=COMFORT)
seller_assigned_id = StringField(NS_RAM, "SellerAssignedID", required=False,
profile=COMFORT)
buyer_assigned_id = StringField(NS_RAM, "BuyerAssignedID", required=False,
profile=COMFORT)
+ name = StringField(NS_RAM, "Name", required=False, profile=COMFORT)
+ description = StringField(NS_RAM, "Description", required=False, profile=COMFORT)
characteristics = MultiField(ProductCharacteristic, required=False, profile=EXTENDED)
classifications = MultiField(ProductClassification, required=False, profile=EXTENDED)
origins = MultiField(OriginCountry, required=False, profile=EXTENDED)
logger = logging.getLogger("drafthorse")
+def minify(xml):
+ try:
+ from lxml import etree
+ return b"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + etree.tostring(etree.fromstring(xml))
+ except ImportError:
+ logger.warning("Could not minify output as LXML is not installed.")
+ return xml
+
+
def prettify(xml):
- reparsed = minidom.parseString(xml)
- return reparsed.toprettyxml(indent="\t")
+ try:
+ from lxml import etree
+ except ImportError:
+ reparsed = minidom.parseString(xml)
+ return reparsed.toprettyxml(indent="\t")
+ else:
+ parser = etree.XMLParser(remove_blank_text=True)
+ return b"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + etree.tostring(
+ etree.fromstring(xml, parser), pretty_print=True
+ )
def validate_xml(xmlout, schema):
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<rsm:CrossIndustryDocument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:rsm="urn:ferd:CrossIndustryDocument:invoice:1p0"
- xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:12"
- xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:15">
- <rsm:SpecifiedExchangedDocumentContext>
- <ram:GuidelineSpecifiedDocumentContextParameter>
- <ram:ID>urn:ferd:CrossIndustryDocument:invoice:1p0:comfort</ram:ID>
- </ram:GuidelineSpecifiedDocumentContextParameter>
- </rsm:SpecifiedExchangedDocumentContext>
- <rsm:HeaderExchangedDocument>
- <ram:ID>RE1337</ram:ID>
- <ram:Name>RECHNUNG</ram:Name>
- <ram:TypeCode>380</ram:TypeCode>
- <ram:IssueDateTime>
- <udt:DateTimeString format="102">20130305</udt:DateTimeString>
- </ram:IssueDateTime>
- <ram:IncludedNote>
- <ram:Content>Test Node 1</ram:Content>
- </ram:IncludedNote>
- <ram:IncludedNote>
- <ram:Content>Test Node 2</ram:Content>
- </ram:IncludedNote>
- <ram:IncludedNote>
- <ram:Content>easybill GmbH
- Düsselstr. 21
- 41564 Kaarst
-
- Geschäftsführer:
- Christian Szardenings
- Ronny Keyser
- </ram:Content>
- <ram:SubjectCode>REG</ram:SubjectCode>
- </ram:IncludedNote>
- </rsm:HeaderExchangedDocument>
- <rsm:SpecifiedSupplyChainTradeTransaction>
- <ram:ApplicableSupplyChainTradeAgreement>
- <ram:SellerTradeParty>
- <ram:Name>Lieferant GmbH</ram:Name>
- <ram:PostalTradeAddress>
- <ram:PostcodeCode>80333</ram:PostcodeCode>
- <ram:LineOne>Lieferantenstraße 20</ram:LineOne>
- <ram:CityName>München</ram:CityName>
- <ram:CountryID>DE</ram:CountryID>
- </ram:PostalTradeAddress>
- <ram:SpecifiedTaxRegistration>
- <ram:ID schemeID="FC">201/113/40209</ram:ID>
- </ram:SpecifiedTaxRegistration>
- <ram:SpecifiedTaxRegistration>
- <ram:ID schemeID="VA">DE123456789</ram:ID>
- </ram:SpecifiedTaxRegistration>
- </ram:SellerTradeParty>
- <ram:BuyerTradeParty>
- <ram:Name>Kunden AG Mitte</ram:Name>
- <ram:PostalTradeAddress>
- <ram:PostcodeCode>69876</ram:PostcodeCode>
- <ram:LineOne>Hans Muster</ram:LineOne>
- <ram:LineTwo>Kundenstraße 15</ram:LineTwo>
- <ram:CityName>Frankfurt</ram:CityName>
- <ram:CountryID>DE</ram:CountryID>
- </ram:PostalTradeAddress>
- </ram:BuyerTradeParty>
- </ram:ApplicableSupplyChainTradeAgreement>
- <ram:ApplicableSupplyChainTradeDelivery>
- <ram:ActualDeliverySupplyChainEvent>
- <ram:OccurrenceDateTime>
- <udt:DateTimeString format="102">20130305</udt:DateTimeString>
- </ram:OccurrenceDateTime>
- </ram:ActualDeliverySupplyChainEvent>
- </ram:ApplicableSupplyChainTradeDelivery>
- <ram:ApplicableSupplyChainTradeSettlement>
- <ram:PaymentReference>2013-471102</ram:PaymentReference>
- <ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode>
- <ram:SpecifiedTradeSettlementPaymentMeans>
- <ram:TypeCode>31</ram:TypeCode>
- <ram:Information>Überweisung</ram:Information>
- <ram:PayeePartyCreditorFinancialAccount>
- <ram:IBANID>DE08700901001234567890</ram:IBANID>
- <ram:AccountName></ram:AccountName>
- <ram:ProprietaryID></ram:ProprietaryID>
- </ram:PayeePartyCreditorFinancialAccount>
- <ram:PayeeSpecifiedCreditorFinancialInstitution>
- <ram:BICID>GENODEF1M04</ram:BICID>
- <ram:GermanBankleitzahlID></ram:GermanBankleitzahlID>
- <ram:Name></ram:Name>
- </ram:PayeeSpecifiedCreditorFinancialInstitution>
- </ram:SpecifiedTradeSettlementPaymentMeans>
- <ram:ApplicableTradeTax>
- <ram:CalculatedAmount currencyID="EUR">19.25</ram:CalculatedAmount>
- <ram:TypeCode>VAT</ram:TypeCode>
- <ram:BasisAmount currencyID="EUR">275.00</ram:BasisAmount>
- <ram:ApplicablePercent>7.00</ram:ApplicablePercent>
- </ram:ApplicableTradeTax>
- <ram:ApplicableTradeTax>
- <ram:CalculatedAmount currencyID="EUR">37.62</ram:CalculatedAmount>
- <ram:TypeCode>VAT</ram:TypeCode>
- <ram:BasisAmount currencyID="EUR">198.00</ram:BasisAmount>
- <ram:ApplicablePercent>19.00</ram:ApplicablePercent>
- </ram:ApplicableTradeTax>
- <ram:SpecifiedTradePaymentTerms>
- <ram:Description>Zahlbar innerhalb von 20 Tagen (bis zum 05.10.2016) unter Abzug von 3% Skonto
- (Zahlungsbetrag = 1.766,03 €). Bis zum 29.09.2016 ohne Abzug.
- </ram:Description>
- <ram:DueDateDateTime>
- <udt:DateTimeString format="102">20130404</udt:DateTimeString>
- </ram:DueDateDateTime>
- </ram:SpecifiedTradePaymentTerms>
- <ram:SpecifiedTradeSettlementMonetarySummation>
- <ram:LineTotalAmount currencyID="EUR">198.00</ram:LineTotalAmount>
- <ram:ChargeTotalAmount currencyID="EUR">0.00</ram:ChargeTotalAmount>
- <ram:AllowanceTotalAmount currencyID="EUR">0.00</ram:AllowanceTotalAmount>
- <ram:TaxBasisTotalAmount currencyID="EUR">198.00</ram:TaxBasisTotalAmount>
- <ram:TaxTotalAmount currencyID="EUR">37.62</ram:TaxTotalAmount>
- <ram:GrandTotalAmount currencyID="EUR">235.62</ram:GrandTotalAmount>
- </ram:SpecifiedTradeSettlementMonetarySummation>
- </ram:ApplicableSupplyChainTradeSettlement>
- <ram:IncludedSupplyChainTradeLineItem>
- <ram:AssociatedDocumentLineDocument>
- <ram:LineID>1</ram:LineID>
- <ram:IncludedNote>
- <ram:Content>Testcontent in einem LineDocument</ram:Content>
- </ram:IncludedNote>
- </ram:AssociatedDocumentLineDocument>
- <ram:SpecifiedSupplyChainTradeAgreement>
- <ram:GrossPriceProductTradePrice>
- <ram:ChargeAmount currencyID="EUR">9.9000</ram:ChargeAmount>
- <ram:AppliedTradeAllowanceCharge>
- <ram:ChargeIndicator>
- <udt:Indicator>false</udt:Indicator>
- </ram:ChargeIndicator>
- <ram:ActualAmount currencyID="EUR">1.8000</ram:ActualAmount>
- </ram:AppliedTradeAllowanceCharge>
- </ram:GrossPriceProductTradePrice>
- <ram:NetPriceProductTradePrice>
- <ram:ChargeAmount currencyID="EUR">9.9000</ram:ChargeAmount>
- </ram:NetPriceProductTradePrice>
- </ram:SpecifiedSupplyChainTradeAgreement>
- <ram:SpecifiedSupplyChainTradeDelivery>
- <ram:BilledQuantity unitCode="C62">20.0000</ram:BilledQuantity>
- </ram:SpecifiedSupplyChainTradeDelivery>
- <ram:SpecifiedSupplyChainTradeSettlement>
- <ram:ApplicableTradeTax>
- <ram:TypeCode>VAT</ram:TypeCode>
- <ram:CategoryCode>S</ram:CategoryCode>
- <ram:ApplicablePercent>19.00</ram:ApplicablePercent>
- </ram:ApplicableTradeTax>
- <ram:SpecifiedTradeSettlementMonetarySummation>
- <ram:LineTotalAmount currencyID="EUR">198.00</ram:LineTotalAmount>
- </ram:SpecifiedTradeSettlementMonetarySummation>
- </ram:SpecifiedSupplyChainTradeSettlement>
- <ram:SpecifiedTradeProduct>
- <ram:SellerAssignedID>TB100A4</ram:SellerAssignedID>
- <ram:Name>Trennblätter A4</ram:Name>
- </ram:SpecifiedTradeProduct>
- </ram:IncludedSupplyChainTradeLineItem>
- </rsm:SpecifiedSupplyChainTradeTransaction>
-</rsm:CrossIndustryDocument>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" ?>
+<rsm:CrossIndustryDocument xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:12" xmlns:rsm="urn:ferd:CrossIndustryDocument:invoice:1p0" xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:15">
+ <rsm:SpecifiedExchangedDocumentContext>
+ <ram:TestIndicator>
+ <udt:Indicator>false</udt:Indicator>
+ </ram:TestIndicator>
+ <ram:GuidelineSpecifiedDocumentContextParameter>
+ <ram:ID>urn:ferd:CrossIndustryDocument:invoice:1p0:comfort</ram:ID>
+ </ram:GuidelineSpecifiedDocumentContextParameter>
+ </rsm:SpecifiedExchangedDocumentContext>
+ <rsm:HeaderExchangedDocument>
+ <ram:ID>RE1337</ram:ID>
+ <ram:Name>RECHNUNG</ram:Name>
+ <ram:TypeCode>380</ram:TypeCode>
+ <ram:IssueDateTime>
+ <udt:DateTimeString format="102">20130305</udt:DateTimeString>
+ </ram:IssueDateTime>
+ <ram:CopyIndicator>
+ <udt:Indicator>false</udt:Indicator>
+ </ram:CopyIndicator>
+ <ram:IncludedNote>
+ <ram:Content>Test Node 1</ram:Content>
+ </ram:IncludedNote>
+ <ram:IncludedNote>
+ <ram:Content>Test Node 2</ram:Content>
+ </ram:IncludedNote>
+ <ram:IncludedNote>
+ <ram:Content>easybill GmbH
+ Düsselstr. 21
+ 41564 Kaarst
+
+ Geschäftsführer:
+ Christian Szardenings
+ Ronny Keyser
+ </ram:Content>
+ <ram:SubjectCode>REG</ram:SubjectCode>
+ </ram:IncludedNote>
+ </rsm:HeaderExchangedDocument>
+ <rsm:SpecifiedSupplyChainTradeTransaction>
+ <ram:ApplicableSupplyChainTradeAgreement>
+ <ram:SellerTradeParty>
+ <ram:Name>Lieferant GmbH</ram:Name>
+ <ram:PostalTradeAddress>
+ <ram:PostcodeCode>80333</ram:PostcodeCode>
+ <ram:LineOne>Lieferantenstraße 20</ram:LineOne>
+ <ram:CityName>München</ram:CityName>
+ <ram:CountryID>DE</ram:CountryID>
+ </ram:PostalTradeAddress>
+ <ram:SpecifiedTaxRegistration>
+ <ram:ID schemeID="FC">201/113/40209</ram:ID>
+ </ram:SpecifiedTaxRegistration>
+ <ram:SpecifiedTaxRegistration>
+ <ram:ID schemeID="VA">DE123456789</ram:ID>
+ </ram:SpecifiedTaxRegistration>
+ </ram:SellerTradeParty>
+ <ram:BuyerTradeParty>
+ <ram:Name>Kunden AG Mitte</ram:Name>
+ <ram:PostalTradeAddress>
+ <ram:PostcodeCode>69876</ram:PostcodeCode>
+ <ram:LineOne>Hans Muster</ram:LineOne>
+ <ram:LineTwo>Kundenstraße 15</ram:LineTwo>
+ <ram:CityName>Frankfurt</ram:CityName>
+ <ram:CountryID>DE</ram:CountryID>
+ </ram:PostalTradeAddress>
+ </ram:BuyerTradeParty>
+ </ram:ApplicableSupplyChainTradeAgreement>
+ <ram:ApplicableSupplyChainTradeDelivery>
+ <ram:ActualDeliverySupplyChainEvent>
+ <ram:OccurrenceDateTime>
+ <udt:DateTimeString format="102">20130305</udt:DateTimeString>
+ </ram:OccurrenceDateTime>
+ </ram:ActualDeliverySupplyChainEvent>
+ </ram:ApplicableSupplyChainTradeDelivery>
+ <ram:ApplicableSupplyChainTradeSettlement>
+ <ram:PaymentReference>2013-471102</ram:PaymentReference>
+ <ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode>
+ <ram:SpecifiedTradeSettlementPaymentMeans>
+ <ram:TypeCode>31</ram:TypeCode>
+ <ram:Information>Überweisung</ram:Information>
+ <ram:PayeePartyCreditorFinancialAccount>
+ <ram:IBANID>DE08700901001234567890</ram:IBANID>
+ </ram:PayeePartyCreditorFinancialAccount>
+ <ram:PayeeSpecifiedCreditorFinancialInstitution>
+ <ram:BICID>GENODEF1M04</ram:BICID>
+ </ram:PayeeSpecifiedCreditorFinancialInstitution>
+ </ram:SpecifiedTradeSettlementPaymentMeans>
+ <ram:ApplicableTradeTax>
+ <ram:CalculatedAmount currencyID="EUR">19.25</ram:CalculatedAmount>
+ <ram:TypeCode>VAT</ram:TypeCode>
+ <ram:BasisAmount currencyID="EUR">275.00</ram:BasisAmount>
+ <ram:ApplicablePercent>7.00</ram:ApplicablePercent>
+ </ram:ApplicableTradeTax>
+ <ram:ApplicableTradeTax>
+ <ram:CalculatedAmount currencyID="EUR">37.62</ram:CalculatedAmount>
+ <ram:TypeCode>VAT</ram:TypeCode>
+ <ram:BasisAmount currencyID="EUR">198.00</ram:BasisAmount>
+ <ram:ApplicablePercent>19.00</ram:ApplicablePercent>
+ </ram:ApplicableTradeTax>
+ <ram:SpecifiedTradePaymentTerms>
+ <ram:Description>Zahlbar innerhalb von 20 Tagen (bis zum 05.10.2016) unter Abzug von 3% Skonto
+ (Zahlungsbetrag = 1.766,03 €). Bis zum 29.09.2016 ohne Abzug.
+ </ram:Description>
+ <ram:DueDateDateTime>
+ <udt:DateTimeString format="102">20130404</udt:DateTimeString>
+ </ram:DueDateDateTime>
+ </ram:SpecifiedTradePaymentTerms>
+ <ram:SpecifiedTradeSettlementMonetarySummation>
+ <ram:LineTotalAmount currencyID="EUR">198.00</ram:LineTotalAmount>
+ <ram:ChargeTotalAmount currencyID="EUR">0.00</ram:ChargeTotalAmount>
+ <ram:AllowanceTotalAmount currencyID="EUR">0.00</ram:AllowanceTotalAmount>
+ <ram:TaxBasisTotalAmount currencyID="EUR">198.00</ram:TaxBasisTotalAmount>
+ <ram:TaxTotalAmount currencyID="EUR">37.62</ram:TaxTotalAmount>
+ <ram:GrandTotalAmount currencyID="EUR">235.62</ram:GrandTotalAmount>
+ </ram:SpecifiedTradeSettlementMonetarySummation>
+ </ram:ApplicableSupplyChainTradeSettlement>
+ <ram:IncludedSupplyChainTradeLineItem>
+ <ram:AssociatedDocumentLineDocument>
+ <ram:LineID>1</ram:LineID>
+ <ram:IncludedNote>
+ <ram:Content>Testcontent in einem LineDocument</ram:Content>
+ </ram:IncludedNote>
+ </ram:AssociatedDocumentLineDocument>
+ <ram:SpecifiedSupplyChainTradeAgreement>
+ <ram:GrossPriceProductTradePrice>
+ <ram:ChargeAmount currencyID="EUR">9.9000</ram:ChargeAmount>
+ <ram:AppliedTradeAllowanceCharge>
+ <ram:ChargeIndicator>
+ <udt:Indicator>false</udt:Indicator>
+ </ram:ChargeIndicator>
+ <ram:ActualAmount currencyID="EUR">1.8000</ram:ActualAmount>
+ </ram:AppliedTradeAllowanceCharge>
+ </ram:GrossPriceProductTradePrice>
+ <ram:NetPriceProductTradePrice>
+ <ram:ChargeAmount currencyID="EUR">9.9000</ram:ChargeAmount>
+ </ram:NetPriceProductTradePrice>
+ </ram:SpecifiedSupplyChainTradeAgreement>
+ <ram:SpecifiedSupplyChainTradeDelivery>
+ <ram:BilledQuantity unitCode="C62">20.0000</ram:BilledQuantity>
+ </ram:SpecifiedSupplyChainTradeDelivery>
+ <ram:SpecifiedSupplyChainTradeSettlement>
+ <ram:ApplicableTradeTax>
+ <ram:TypeCode>VAT</ram:TypeCode>
+ <ram:CategoryCode>S</ram:CategoryCode>
+ <ram:ApplicablePercent>19.00</ram:ApplicablePercent>
+ </ram:ApplicableTradeTax>
+ <ram:SpecifiedTradeSettlementMonetarySummation>
+ <ram:LineTotalAmount currencyID="EUR">198.00</ram:LineTotalAmount>
+ </ram:SpecifiedTradeSettlementMonetarySummation>
+ </ram:SpecifiedSupplyChainTradeSettlement>
+ <ram:SpecifiedTradeProduct>
+ <ram:SellerAssignedID>TB100A4</ram:SellerAssignedID>
+ <ram:Name>Trennblätter A4</ram:Name>
+ </ram:SpecifiedTradeProduct>
+ </ram:IncludedSupplyChainTradeLineItem>
+ </rsm:SpecifiedSupplyChainTradeTransaction>
+</rsm:CrossIndustryDocument>
+
--- /dev/null
+import os
+
+import pytest
+
+from drafthorse.models.document import Document
+from drafthorse.utils import prettify
+
+samples = [
+ 'easybill_sample.xml',
+]
+
+
+@pytest.mark.parametrize("filename", samples)
+def test_sample_roundtrip(filename):
+ origxml = prettify(open(os.path.join(os.path.dirname(__file__), 'samples', filename), 'r').read())
+ doc = Document.parse(origxml)
+ generatedxml = prettify(doc.serialize())
+ assert generatedxml.decode().strip() == origxml.decode().strip()
\ No newline at end of file