public bool IsReadableByThisReaderVersion(Stream stream, ZugferdDialect zugferdDialect)
        {
            if (!stream.CanRead)
            {
                throw new IllegalStreamException("Cannot read from stream");
            }

            XmlDocument doc = new XmlDocument();

            doc.Load(stream);

            if (doc.DocumentElement?.OwnerDocument?.NameTable == null)
            {
                return(false);
            }
            XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.DocumentElement.OwnerDocument.NameTable);

            foreach ((string item1, string item2) in zugferdDialect.GetNamespaces())
            {
                nsmgr.AddNamespace(item1, item2);
            }

            string profile = NodeAsString(doc.DocumentElement, "//ram:GuidelineSpecifiedDocumentContextParameter/ram:ID", nsmgr);

            if (profile.StartsWith(zugferdDialect.DocumentId))
            {
                return(true);
            }
            return(false);
        }
        public InvoiceDescriptor Load(Stream stream, ZugferdDialect zugferdDialect)
        {
            if (!stream.CanRead)
            {
                throw new IllegalStreamException("Cannot read from stream");
            }

            XmlDocument doc = new XmlDocument();

            doc.Load(stream);

            if (doc.DocumentElement?.OwnerDocument?.NameTable == null)
            {
                return(null);
            }
            XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.DocumentElement.OwnerDocument.NameTable);

            foreach ((string item1, string item2) in zugferdDialect.GetNamespaces())
            {
                nsmgr.AddNamespace(item1, item2);
            }

            InvoiceDescriptor retval;

            retval             = new InvoiceDescriptor();
            retval.IsTest      = NodeAsBool(doc.DocumentElement, $"//rsm:{zugferdDialect.ExchangedDocument}/ram:TestIndicator", nsmgr);
            retval.Profile     = default(Profile).FromString(NodeAsString(doc.DocumentElement, "//ram:GuidelineSpecifiedDocumentContextParameter/ram:ID", nsmgr));
            retval.Type        = default(InvoiceType).FromString(NodeAsString(doc.DocumentElement, $"//rsm:{zugferdDialect.ExchangedDocument}/ram:TypeCode", nsmgr));
            retval.InvoiceNo   = NodeAsString(doc.DocumentElement, $"//rsm:{zugferdDialect.ExchangedDocument}/ram:ID", nsmgr);
            retval.InvoiceDate = NodeAsDateTime(doc.DocumentElement, $"//rsm:{zugferdDialect.ExchangedDocument}/ram:IssueDateTime/udt:DateTimeString", nsmgr);

            foreach (XmlNode node in doc.SelectNodes($"//rsm:{zugferdDialect.ExchangedDocument}/ram:IncludedNote", nsmgr))
            {
                string       content         = NodeAsString(node, ".//ram:Content", nsmgr);
                string       subjectCode     = NodeAsString(node, ".//ram:SubjectCode", nsmgr);
                SubjectCodes subjectCodeEnum = default(SubjectCodes).FromString(subjectCode);
                retval.AddNote(content, subjectCodeEnum);
            }

            retval.ReferenceOrderNo = NodeAsString(doc, $"//ram:{zugferdDialect.ApplicableTradeAgreement}/ram:BuyerReference", nsmgr);

            retval.Seller = NodeAsParty(doc.DocumentElement, $"//ram:{zugferdDialect.ApplicableTradeAgreement}/ram:SellerTradeParty", nsmgr);
            foreach (XmlNode node in doc.SelectNodes($"//ram:{zugferdDialect.ApplicableTradeAgreement}/ram:SellerTradeParty/ram:SpecifiedTaxRegistration", nsmgr))
            {
                string id       = NodeAsString(node, ".//ram:ID", nsmgr);
                string schemeID = NodeAsString(node, ".//ram:ID/@schemeID", nsmgr);

                retval.AddSellerTaxRegistration(id, default(TaxRegistrationSchemeID).FromString(schemeID));
            }

            if (doc.SelectSingleNode("//ram:SellerTradeParty/ram:DefinedTradeContact", nsmgr) != null)
            {
                retval.SellerContact = new Contact
                {
                    Name         = NodeAsString(doc.DocumentElement, "//ram:SellerTradeParty/ram:DefinedTradeContact/ram:PersonName", nsmgr),
                    OrgUnit      = NodeAsString(doc.DocumentElement, "//ram:SellerTradeParty/ram:DefinedTradeContact/ram:DepartmentName", nsmgr),
                    PhoneNo      = NodeAsString(doc.DocumentElement, "//ram:SellerTradeParty/ram:DefinedTradeContact/ram:TelephoneUniversalCommunication/ram:CompleteNumber", nsmgr),
                    FaxNo        = NodeAsString(doc.DocumentElement, "//ram:SellerTradeParty/ram:DefinedTradeContact/ram:FaxUniversalCommunication/ram:CompleteNumber", nsmgr),
                    EmailAddress = NodeAsString(doc.DocumentElement, "//ram:SellerTradeParty/ram:DefinedTradeContact/ram:EmailURIUniversalCommunication/ram:CompleteNumber", nsmgr)
                };
            }

            retval.Buyer = NodeAsParty(doc.DocumentElement, $"//ram:{zugferdDialect.ApplicableTradeAgreement}/ram:BuyerTradeParty", nsmgr);
            foreach (XmlNode node in doc.SelectNodes($"//ram:{zugferdDialect.ApplicableTradeAgreement}/ram:BuyerTradeParty/ram:SpecifiedTaxRegistration", nsmgr))
            {
                string id       = NodeAsString(node, ".//ram:ID", nsmgr);
                string schemeID = NodeAsString(node, ".//ram:ID/@schemeID", nsmgr);

                retval.AddBuyerTaxRegistration(id, default(TaxRegistrationSchemeID).FromString(schemeID));
            }

            if (doc.SelectSingleNode("//ram:BuyerTradeParty/ram:DefinedTradeContact", nsmgr) != null)
            {
                retval.BuyerContact = new Contact
                {
                    Name         = NodeAsString(doc.DocumentElement, "//ram:BuyerTradeParty/ram:DefinedTradeContact/ram:PersonName", nsmgr),
                    OrgUnit      = NodeAsString(doc.DocumentElement, "//ram:BuyerTradeParty/DefinedTradeContact/ram:DepartmentName", nsmgr),
                    PhoneNo      = NodeAsString(doc.DocumentElement, "//ram:BuyerTradeParty/ram:DefinedTradeContact/ram:TelephoneUniversalCommunication/ram:CompleteNumber", nsmgr),
                    FaxNo        = NodeAsString(doc.DocumentElement, "//ram:BuyerTradeParty/ram:DefinedTradeContact/ram:FaxUniversalCommunication/ram:CompleteNumber", nsmgr),
                    EmailAddress = NodeAsString(doc.DocumentElement, "//ram:BuyerTradeParty/ram:DefinedTradeContact/ram:EmailURIUniversalCommunication/ram:CompleteNumber", nsmgr)
                };
            }

            retval.ShipTo             = NodeAsParty(doc.DocumentElement, $"//ram:{zugferdDialect.ApplicableTradeDelivery}/ram:ShipToTradeParty", nsmgr);
            retval.ShipFrom           = NodeAsParty(doc.DocumentElement, $"//ram:{zugferdDialect.ApplicableTradeDelivery}/ram:ShipFromTradeParty", nsmgr);
            retval.ActualDeliveryDate = NodeAsDateTime(doc.DocumentElement, $"//ram:{zugferdDialect.ApplicableTradeDelivery}/ram:ActualDeliverySupplyChainEvent/ram:OccurrenceDateTime/udt:DateTimeString", nsmgr);

            string   deliveryNoteNo   = NodeAsString(doc.DocumentElement, $"//ram:{zugferdDialect.ApplicableTradeDelivery}/ram:DeliveryNoteReferencedDocument/ram:ID", nsmgr);
            DateTime?deliveryNoteDate = NodeAsDateTime(doc.DocumentElement, $"//ram:{zugferdDialect.ApplicableTradeDelivery}/ram:DeliveryNoteReferencedDocument/ram:IssueDateTime/udt:DateTimeString", nsmgr) ?? NodeAsDateTime(doc.DocumentElement, $"//ram:{zugferdDialect.ApplicableTradeDelivery}/ram:DeliveryNoteReferencedDocument/ram:IssueDateTime", nsmgr);

            if (deliveryNoteDate.HasValue || !string.IsNullOrEmpty(deliveryNoteNo))
            {
                retval.DeliveryNoteReferencedDocument = new DeliveryNoteReferencedDocument
                {
                    ID            = deliveryNoteNo,
                    IssueDateTime = deliveryNoteDate
                };
            }

            retval.Invoicee = NodeAsParty(doc.DocumentElement, $"//ram:{zugferdDialect.ApplicableTradeSettlement}/ram:InvoiceeTradeParty", nsmgr);
            retval.Payee    = NodeAsParty(doc.DocumentElement, $"//ram:{zugferdDialect.ApplicableTradeSettlement}/ram:PayeeTradeParty", nsmgr);

            retval.InvoiceNoAsReference = NodeAsString(doc.DocumentElement, $"//ram:{zugferdDialect.ApplicableTradeSettlement}/ram:PaymentReference", nsmgr);
            retval.Currency             = default(CurrencyCodes).FromString(NodeAsString(doc.DocumentElement, $"//ram:{zugferdDialect.ApplicableTradeSettlement}/ram:InvoiceCurrencyCode", nsmgr));

            // TODO: Multiple SpecifiedTradeSettlementPaymentMeans can exist for each account/institution (with different SEPA?)
            PaymentMeans tempPaymentMeans = new PaymentMeans
            {
                TypeCode               = default(PaymentMeansTypeCodes).FromString(NodeAsString(doc.DocumentElement, $"//ram:{zugferdDialect.ApplicableTradeSettlement}/ram:SpecifiedTradeSettlementPaymentMeans/ram:TypeCode", nsmgr)),
                Information            = NodeAsString(doc.DocumentElement, $"//ram:{zugferdDialect.ApplicableTradeSettlement}/ram:SpecifiedTradeSettlementPaymentMeans/ram:Information", nsmgr),
                SEPACreditorIdentifier = NodeAsString(doc.DocumentElement, $"//ram:{zugferdDialect.ApplicableTradeSettlement}/ram:SpecifiedTradeSettlementPaymentMeans/ram:ID", nsmgr),
                SEPAMandateReference   = NodeAsString(doc.DocumentElement, $"//ram:{zugferdDialect.ApplicableTradeSettlement}/ram:SpecifiedTradeSettlementPaymentMeans/ram:ID/@schemeAgencyID", nsmgr)
            };

            retval.PaymentMeans = tempPaymentMeans;

            XmlNodeList creditorFinancialAccountNodes = doc.SelectNodes($"//ram:{zugferdDialect.ApplicableTradeSettlement}/ram:SpecifiedTradeSettlementPaymentMeans/ram:PayeePartyCreditorFinancialAccount", nsmgr);
            XmlNodeList creditorFinancialInstitutions = doc.SelectNodes($"//ram:{zugferdDialect.ApplicableTradeSettlement}/ram:SpecifiedTradeSettlementPaymentMeans/ram:PayeeSpecifiedCreditorFinancialInstitution", nsmgr);

            if (creditorFinancialAccountNodes.Count == creditorFinancialInstitutions.Count)
            {
                for (int i = 0; i < creditorFinancialAccountNodes.Count; i++)
                {
                    BankAccount account = new BankAccount
                    {
                        ID           = NodeAsString(creditorFinancialAccountNodes[0], ".//ram:ProprietaryID", nsmgr),
                        IBAN         = NodeAsString(creditorFinancialAccountNodes[0], ".//ram:IBANID", nsmgr),
                        BIC          = NodeAsString(creditorFinancialInstitutions[0], ".//ram:BICID", nsmgr),
                        Bankleitzahl = NodeAsString(creditorFinancialInstitutions[0], ".//ram:GermanBankleitzahlID", nsmgr),
                        BankName     = NodeAsString(creditorFinancialInstitutions[0], ".//ram:Name", nsmgr),
                        Name         = NodeAsString(creditorFinancialInstitutions[0], ".//ram:AccountName", nsmgr)
                    };

                    retval.CreditorBankAccounts.Add(account);
                }
            }

            XmlNodeList debitorFinancialAccountNodes = doc.SelectNodes($"//ram:{zugferdDialect.ApplicableTradeSettlement}/ram:SpecifiedTradeSettlementPaymentMeans/ram:PayerPartyDebtorFinancialAccount", nsmgr);
            XmlNodeList debitorFinancialInstitutions = doc.SelectNodes($"//ram:{zugferdDialect.ApplicableTradeSettlement}/ram:SpecifiedTradeSettlementPaymentMeans/ram:PayerSpecifiedDebtorFinancialInstitution", nsmgr);

            if (debitorFinancialAccountNodes.Count == debitorFinancialInstitutions.Count)
            {
                for (int i = 0; i < debitorFinancialAccountNodes.Count; i++)
                {
                    BankAccount account = new BankAccount
                    {
                        ID           = NodeAsString(debitorFinancialAccountNodes[0], ".//ram:ProprietaryID", nsmgr),
                        IBAN         = NodeAsString(debitorFinancialAccountNodes[0], ".//ram:IBANID", nsmgr),
                        BIC          = NodeAsString(debitorFinancialInstitutions[0], ".//ram:BICID", nsmgr),
                        Bankleitzahl = NodeAsString(debitorFinancialInstitutions[0], ".//ram:GermanBankleitzahlID", nsmgr),
                        BankName     = NodeAsString(debitorFinancialInstitutions[0], ".//ram:Name", nsmgr)
                    };

                    retval.DebitorBankAccounts.Add(account);
                } // !for(i)
            }

            foreach (XmlNode node in doc.SelectNodes($"//ram:{zugferdDialect.ApplicableTradeSettlement}/ram:ApplicableTradeTax", nsmgr))
            {
                retval.AddApplicableTradeTax(NodeAsDecimal(node, ".//ram:BasisAmount", nsmgr, 0).Value,
                                             NodeAsDecimal(node, $".//ram:{zugferdDialect.ApplicablePercent}", nsmgr, 0).Value,
                                             default(TaxTypes).FromString(NodeAsString(node, ".//ram:TypeCode", nsmgr)),
                                             default(TaxCategoryCodes).FromString(NodeAsString(node, ".//ram:CategoryCode", nsmgr)));
            }

            foreach (XmlNode node in doc.SelectNodes("//ram:SpecifiedTradeAllowanceCharge", nsmgr))
            {
                retval.AddTradeAllowanceCharge(!NodeAsBool(node, ".//ram:ChargeIndicator", nsmgr), // wichtig: das not (!) beachten
                                               NodeAsDecimal(node, ".//ram:BasisAmount", nsmgr, 0).Value,
                                               retval.Currency,
                                               NodeAsDecimal(node, ".//ram:ActualAmount", nsmgr, 0).Value,
                                               NodeAsString(node, ".//ram:Reason", nsmgr),
                                               default(TaxTypes).FromString(NodeAsString(node, ".//ram:CategoryTradeTax/ram:TypeCode", nsmgr)),
                                               default(TaxCategoryCodes).FromString(NodeAsString(node, ".//ram:CategoryTradeTax/ram:CategoryCode", nsmgr)),
                                               NodeAsDecimal(node, $".//ram:CategoryTradeTax/ram:{zugferdDialect.ApplicablePercent}", nsmgr, 0).Value);
            }

            foreach (XmlNode node in doc.SelectNodes("//ram:SpecifiedLogisticsServiceCharge", nsmgr))
            {
                retval.AddLogisticsServiceCharge(NodeAsDecimal(node, ".//ram:AppliedAmount", nsmgr, 0).Value,
                                                 NodeAsString(node, ".//ram:Description", nsmgr),
                                                 default(TaxTypes).FromString(NodeAsString(node, ".//ram:AppliedTradeTax/ram:TypeCode", nsmgr)),
                                                 default(TaxCategoryCodes).FromString(NodeAsString(node, ".//ram:AppliedTradeTax/ram:CategoryCode", nsmgr)),
                                                 NodeAsDecimal(node, $".//ram:AppliedTradeTax/ram:{zugferdDialect.ApplicablePercent}", nsmgr, 0).Value);
            }

            retval.PaymentTerms = new PaymentTerms
            {
                Description = NodeAsString(doc.DocumentElement, "//ram:SpecifiedTradePaymentTerms/ram:Description", nsmgr),
                DueDate     = NodeAsDateTime(doc.DocumentElement, "//ram:SpecifiedTradePaymentTerms/ram:DueDateDateTime", nsmgr)
            };

            retval.LineTotalAmount      = NodeAsDecimal(doc.DocumentElement, $"//ram:{zugferdDialect.SpecifiedTradeSettlementMonetarySummation}/ram:LineTotalAmount", nsmgr, 0).Value;
            retval.ChargeTotalAmount    = NodeAsDecimal(doc.DocumentElement, $"//ram:{zugferdDialect.SpecifiedTradeSettlementMonetarySummation}/ram:ChargeTotalAmount", nsmgr, 0).Value;
            retval.AllowanceTotalAmount = NodeAsDecimal(doc.DocumentElement, $"//ram:{zugferdDialect.SpecifiedTradeSettlementMonetarySummation}/ram:AllowanceTotalAmount", nsmgr, 0).Value;
            retval.TaxBasisAmount       = NodeAsDecimal(doc.DocumentElement, $"//ram:{zugferdDialect.SpecifiedTradeSettlementMonetarySummation}/ram:TaxBasisTotalAmount", nsmgr, 0).Value;
            retval.TaxTotalAmount       = NodeAsDecimal(doc.DocumentElement, $"//ram:{zugferdDialect.SpecifiedTradeSettlementMonetarySummation}/ram:TaxTotalAmount", nsmgr, 0).Value;
            retval.GrandTotalAmount     = NodeAsDecimal(doc.DocumentElement, $"//ram:{zugferdDialect.SpecifiedTradeSettlementMonetarySummation}/ram:GrandTotalAmount", nsmgr, 0).Value;
            retval.TotalPrepaidAmount   = NodeAsDecimal(doc.DocumentElement, $"//ram:{zugferdDialect.SpecifiedTradeSettlementMonetarySummation}/ram:TotalPrepaidAmount", nsmgr, 0).Value;
            retval.DuePayableAmount     = NodeAsDecimal(doc.DocumentElement, $"//ram:{zugferdDialect.SpecifiedTradeSettlementMonetarySummation}/ram:DuePayableAmount", nsmgr, 0).Value;

            retval.OrderDate = NodeAsDateTime(doc.DocumentElement, $"//ram:{zugferdDialect.ApplicableTradeAgreement}/ram:BuyerOrderReferencedDocument/ram:IssueDateTime/udt:DateTimeString", nsmgr) ?? NodeAsDateTime(doc.DocumentElement, $"//ram:{zugferdDialect.ApplicableTradeAgreement}/ram:BuyerOrderReferencedDocument/ram:IssueDateTime", nsmgr);
            retval.OrderNo   = NodeAsString(doc.DocumentElement, $"//ram:{zugferdDialect.ApplicableTradeAgreement}/ram:BuyerOrderReferencedDocument/ram:ID", nsmgr);

            foreach (XmlNode node in doc.SelectNodes("//ram:IncludedSupplyChainTradeLineItem", nsmgr))
            {
                retval.TradeLineItems.Add(ParseTradeLineItem(node, nsmgr, zugferdDialect));
            }
            return(retval);
        }
        private static TradeLineItem ParseTradeLineItem(XmlNode tradeLineItem, XmlNamespaceManager nsmgr, ZugferdDialect zugferdDialect)
        {
            if (tradeLineItem == null)
            {
                return(null);
            }

            TradeLineItem item = new TradeLineItem
            {
                GlobalID = new GlobalID(NodeAsString(tradeLineItem, ".//ram:SpecifiedTradeProduct/ram:GlobalID/@schemeID", nsmgr),
                                        NodeAsString(tradeLineItem, ".//ram:SpecifiedTradeProduct/ram:GlobalID", nsmgr)),
                SellerAssignedID = NodeAsString(tradeLineItem, ".//ram:SpecifiedTradeProduct/ram:SellerAssignedID", nsmgr),
                BuyerAssignedID  = NodeAsString(tradeLineItem, ".//ram:SpecifiedTradeProduct/ram:BuyerAssignedID", nsmgr),
                Name             = NodeAsString(tradeLineItem, ".//ram:SpecifiedTradeProduct/ram:Name", nsmgr),
                Description      = NodeAsString(tradeLineItem, ".//ram:SpecifiedTradeProduct/ram:Description", nsmgr),
                UnitQuantity     = NodeAsDecimal(tradeLineItem, ".//ram:BasisQuantity", nsmgr, 1),
                BilledQuantity   = NodeAsDecimal(tradeLineItem, ".//ram:BilledQuantity", nsmgr, 0).Value,
                LineTotalAmount  = NodeAsDecimal(tradeLineItem, ".//ram:LineTotalAmount", nsmgr, 0),
                TaxCategoryCode  = default(TaxCategoryCodes).FromString(NodeAsString(tradeLineItem, ".//ram:ApplicableTradeTax/ram:CategoryCode", nsmgr)),
                TaxType          = default(TaxTypes).FromString(NodeAsString(tradeLineItem, ".//ram:ApplicableTradeTax/ram:TypeCode", nsmgr)),
                TaxPercent       = NodeAsDecimal(tradeLineItem, $".//ram:ApplicableTradeTax/ram:{zugferdDialect.ApplicablePercent}", nsmgr, 0).Value,
                NetUnitPrice     = NodeAsDecimal(tradeLineItem, ".//ram:NetPriceProductTradePrice/ram:ChargeAmount", nsmgr, 0).Value,
                GrossUnitPrice   = NodeAsDecimal(tradeLineItem, ".//ram:GrossPriceProductTradePrice/ram:ChargeAmount", nsmgr, 0).Value,
                UnitCode         = default(QuantityCodes).FromString(NodeAsString(tradeLineItem, ".//ram:BasisQuantity/@unitCode", nsmgr))
            };

            if (tradeLineItem.SelectSingleNode(".//ram:AssociatedDocumentLineDocument", nsmgr) != null)
            {
                item.AssociatedDocument = new AssociatedDocument
                {
                    LineID = NodeAsInt(tradeLineItem, ".//ram:AssociatedDocumentLineDocument/ram:LineID", nsmgr, int.MaxValue)
                };

                XmlNodeList noteNodes = tradeLineItem.SelectNodes(".//ram:AssociatedDocumentLineDocument/ram:IncludedNote", nsmgr);
                foreach (XmlNode noteNode in noteNodes)
                {
                    item.AssociatedDocument.Notes.Add(new Note(
                                                          content: NodeAsString(noteNode, ".//ram:Content", nsmgr),
                                                          subjectCode: default(SubjectCodes).FromString(NodeAsString(noteNode, ".//ram:SubjectCode", nsmgr)),
                                                          contentCode: ContentCodes.Unknown
                                                          ));
                }

                if (item.AssociatedDocument.LineID == int.MaxValue) // a bit dirty, but works for now
                {
                    item.AssociatedDocument.LineID = null;
                }
            }

            XmlNodeList appliedTradeAllowanceChargeNodes = tradeLineItem.SelectNodes($".//ram:{zugferdDialect.SpecifiedLineTradeAgreement}/ram:GrossPriceProductTradePrice/ram:AppliedTradeAllowanceCharge", nsmgr);

            foreach (XmlNode appliedTradeAllowanceChargeNode in appliedTradeAllowanceChargeNodes)
            {
                bool    chargeIndicator      = NodeAsBool(appliedTradeAllowanceChargeNode, "./ram:ChargeIndicator/udt:Indicator", nsmgr);
                decimal basisAmount          = NodeAsDecimal(appliedTradeAllowanceChargeNode, "./ram:BasisAmount", nsmgr, 0).Value;
                string  basisAmountCurrency  = NodeAsString(appliedTradeAllowanceChargeNode, "./ram:BasisAmount/@currencyID", nsmgr);
                decimal actualAmount         = NodeAsDecimal(appliedTradeAllowanceChargeNode, "./ram:ActualAmount", nsmgr, 0).Value;
                string  actualAmountCurrency = NodeAsString(appliedTradeAllowanceChargeNode, "./ram:ActualAmount/@currencyID", nsmgr);
                string  reason = NodeAsString(appliedTradeAllowanceChargeNode, "./ram:Reason", nsmgr);

                item.addTradeAllowanceCharge(!chargeIndicator, // wichtig: das not (!) beachten
                                             default(CurrencyCodes).FromString(basisAmountCurrency),
                                             basisAmount,
                                             actualAmount,
                                             reason);
            }

            if (item.UnitCode == QuantityCodes.Unknown)
            {
                // UnitCode alternativ aus BilledQuantity extrahieren
                item.UnitCode = default(QuantityCodes).FromString(NodeAsString(tradeLineItem, ".//ram:BilledQuantity/@unitCode", nsmgr));
            }

            if (tradeLineItem.SelectSingleNode($".//ram:{zugferdDialect.SpecifiedLineTradeAgreement}/ram:BuyerOrderReferencedDocument/ram:ID", nsmgr) != null)
            {
                item.BuyerOrderReferencedDocument = new BuyerOrderReferencedDocument
                {
                    ID            = NodeAsString(tradeLineItem, $".//ram:{zugferdDialect.SpecifiedLineTradeAgreement}/ram:BuyerOrderReferencedDocument/ram:ID", nsmgr),
                    IssueDateTime = NodeAsDateTime(tradeLineItem, $".//ram:{zugferdDialect.SpecifiedLineTradeAgreement}/ram:BuyerOrderReferencedDocument/ram:IssueDateTime", nsmgr)
                };
            }

            if (tradeLineItem.SelectSingleNode($".//ram:{zugferdDialect.SpecifiedLineTradeDelivery}/ram:DeliveryNoteReferencedDocument/ram:ID", nsmgr) != null)
            {
                item.DeliveryNoteReferencedDocument = new DeliveryNoteReferencedDocument
                {
                    ID            = NodeAsString(tradeLineItem, $".//ram:{zugferdDialect.SpecifiedLineTradeDelivery}/ram:DeliveryNoteReferencedDocument/ram:ID", nsmgr),
                    IssueDateTime = NodeAsDateTime(tradeLineItem, $".//ram:{zugferdDialect.SpecifiedLineTradeDelivery}/ram:DeliveryNoteReferencedDocument/ram:IssueDateTime", nsmgr)
                };
            }

            if (tradeLineItem.SelectSingleNode($".//ram:{zugferdDialect.SpecifiedLineTradeDelivery}/ram:ActualDeliverySupplyChainEvent/ram:OccurrenceDateTime", nsmgr) != null)
            {
                item.ActualDeliveryDate = NodeAsDateTime(tradeLineItem, $".//ram:{zugferdDialect.SpecifiedLineTradeDelivery}/ram:ActualDeliverySupplyChainEvent/ram:OccurrenceDateTime/udt:DateTimeString", nsmgr);
            }

            if (tradeLineItem.SelectSingleNode($".//ram:{zugferdDialect.SpecifiedLineTradeAgreement}/ram:ContractReferencedDocument/ram:ID", nsmgr) != null)
            {
                item.ContractReferencedDocument = new ContractReferencedDocument
                {
                    ID            = NodeAsString(tradeLineItem, $".//ram:{zugferdDialect.SpecifiedLineTradeAgreement}/ram:ContractReferencedDocument/ram:ID", nsmgr),
                    IssueDateTime = NodeAsDateTime(tradeLineItem, $".//ram:{zugferdDialect.SpecifiedLineTradeAgreement}/ram:ContractReferencedDocument/ram:IssueDateTime", nsmgr)
                };
            }

            XmlNodeList referenceNodes = tradeLineItem.SelectNodes($".//ram:{zugferdDialect.SpecifiedLineTradeAgreement}/ram:AdditionalReferencedDocument", nsmgr);

            foreach (XmlNode referenceNode in referenceNodes)
            {
                string _code = NodeAsString(referenceNode, "ram:ReferenceTypeCode", nsmgr);

                item.addAdditionalReferencedDocument(
                    id: NodeAsString(referenceNode, "ram:ID", nsmgr),
                    date: NodeAsDateTime(referenceNode, "ram:IssueDateTim", nsmgr),
                    code: default(ReferenceTypeCodes).FromString(_code)
                    );
            }

            if (tradeLineItem.SelectSingleNode($".//ram:{zugferdDialect.SpecifiedLineTradeAgreement}/ram:ContractReferencedDocument/ram:ID", nsmgr) != null)
            {
                item.ContractReferencedDocument = new ContractReferencedDocument
                {
                    ID            = NodeAsString(tradeLineItem, $".//ram:{zugferdDialect.SpecifiedLineTradeAgreement}/ram:ContractReferencedDocument/ram:ID", nsmgr),
                    IssueDateTime = NodeAsDateTime(tradeLineItem, $".//ram:{zugferdDialect.SpecifiedLineTradeAgreement}/ram:ContractReferencedDocument/ram:IssueDateTime", nsmgr)
                };
            }

            return(item);
        } // !ParseTradeLineItem()