/// <summary>
        /// Generate the Transaction XML part
        /// </summary>
        /// <param name="pmtInf">The root nodes for a transaction</param>
        /// <param name="transfer">The transaction to generate</param>
        private void GenerateTransaction(XmlElement pmtInf, SepaCreditTransferTransaction transfer)
        {
            var cdtTrfTxInf = pmtInf.NewElement("CdtTrfTxInf");
            var pmtId       = cdtTrfTxInf.NewElement("PmtId");

            if (transfer.Id != null)
            {
                pmtId.NewElement("InstrId", transfer.Id);
            }
            pmtId.NewElement("EndToEndId", transfer.EndToEndId);
            cdtTrfTxInf.NewElement("Amt")
            .NewElement("InstdAmt", StringUtils.FormatAmount(transfer.Amount))
            .SetAttribute("Ccy", transfer.Currency);
            XmlUtils.CreateBic(cdtTrfTxInf.NewElement("CdtrAgt"), transfer.Creditor);

            var cdtr = cdtTrfTxInf.NewElement("Cdtr");

            cdtr.NewElement("Nm", transfer.Creditor.Name);
            if (transfer.Creditor.Address != null)
            {
                XmlUtils.AddPostalAddressElements(cdtr, transfer.Creditor.Address);
            }

            cdtTrfTxInf.NewElement("CdtrAcct").NewElement("Id").NewElement("IBAN", transfer.Creditor.Iban);

            if (IsInternational && transfer.SepaInstructionForCreditor != null)
            {
                var instr = cdtTrfTxInf.NewElement("InstrForCdtrAgt");
                instr.NewElement("Cd", transfer.SepaInstructionForCreditor.Code);
                if (!string.IsNullOrEmpty(transfer.SepaInstructionForCreditor.Comment))
                {
                    instr.NewElement("InstrInf", transfer.SepaInstructionForCreditor.Comment);
                }
            }

            if (!string.IsNullOrEmpty(transfer.Purpose))
            {
                cdtTrfTxInf.NewElement("Purp").NewElement("Cd", transfer.Purpose);
            }

            if (IsInternational && !string.IsNullOrEmpty(transfer.RegulatoryReportingCode))
            {
                cdtTrfTxInf.NewElement("RgltryRptg").NewElement("Dtls").NewElement("Cd", transfer.RegulatoryReportingCode);
            }

            if (!string.IsNullOrEmpty(transfer.RemittanceInformation))
            {
                cdtTrfTxInf.NewElement("RmtInf").NewElement("Ustrd", transfer.RemittanceInformation);
            }
        }
        /// <summary>
        ///     Generate the XML structure
        /// </summary>
        /// <returns></returns>
        protected override XmlDocument GenerateXml()
        {
            CheckMandatoryData();

            var xml = new XmlDocument();

            xml.AppendChild(xml.CreateXmlDeclaration("1.0", Encoding.UTF8.BodyName, "yes"));
            var el = (XmlElement)xml.AppendChild(xml.CreateElement("Document"));

            el.SetAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
            el.SetAttribute("xmlns", "urn:iso:std:iso:20022:tech:xsd:" + SepaSchemaUtils.SepaSchemaToString(schema));
            el.NewElement("CstmrCdtTrfInitn");

            // Part 1: Group Header
            var grpHdr = XmlUtils.GetFirstElement(xml, "CstmrCdtTrfInitn").NewElement("GrpHdr");

            grpHdr.NewElement("MsgId", MessageIdentification);
            grpHdr.NewElement("CreDtTm", StringUtils.FormatDateTime(CreationDate));
            grpHdr.NewElement("NbOfTxs", numberOfTransactions);
            grpHdr.NewElement("CtrlSum", StringUtils.FormatAmount(headerControlSum));
            if (!String.IsNullOrEmpty(InitiatingPartyName) || InitiatingPartyId != null)
            {
                var initgPty = grpHdr.NewElement("InitgPty");

                if (!String.IsNullOrEmpty(InitiatingPartyName))
                {
                    initgPty.NewElement("Nm", InitiatingPartyName);
                }

                if (InitiatingPartyId != null)
                {
                    initgPty.
                    NewElement("Id").NewElement("OrgId").
                    NewElement("Othr").NewElement("Id", InitiatingPartyId);
                }
            }

            // Part 2: Payment Information
            var pmtInf = XmlUtils.GetFirstElement(xml, "CstmrCdtTrfInitn").NewElement("PmtInf");

            pmtInf.NewElement("PmtInfId", PaymentInfoId ?? MessageIdentification);

            pmtInf.NewElement("PmtMtd", Constant.CreditTransfertPaymentMethod);
            pmtInf.NewElement("NbOfTxs", numberOfTransactions);
            pmtInf.NewElement("CtrlSum", StringUtils.FormatAmount(paymentControlSum));

            if (IsInternational)
            {
                pmtInf.NewElement("PmtTpInf").NewElement("InstrPrty", "NORM");
            }
            else
            {
                pmtInf.NewElement("PmtTpInf").NewElement("SvcLvl").NewElement("Cd", "SEPA");
            }
            if (LocalInstrumentCode != null)
            {
                XmlUtils.GetFirstElement(pmtInf, "PmtTpInf").NewElement("LclInstr")
                .NewElement("Cd", LocalInstrumentCode);
            }

            if (CategoryPurposeCode != null)
            {
                XmlUtils.GetFirstElement(pmtInf, "PmtTpInf").
                NewElement("CtgyPurp").
                NewElement("Cd", CategoryPurposeCode);
            }

            pmtInf.NewElement("ReqdExctnDt", StringUtils.FormatDate(RequestedExecutionDate));
            var dbtr = pmtInf.NewElement("Dbtr");

            dbtr.NewElement("Nm", Debtor.Name);
            if (Debtor.Address != null)
            {
                XmlUtils.AddPostalAddressElements(dbtr, Debtor.Address);
            }
            if (InitiatingPartyId != null)
            {
                XmlUtils.GetFirstElement(pmtInf, "Dbtr").
                NewElement("Id").NewElement("OrgId").
                NewElement("Othr").NewElement("Id", InitiatingPartyId);
            }

            var dbtrAcct   = pmtInf.NewElement("DbtrAcct");
            var dbtrAcctId = dbtrAcct.NewElement("Id");

            if (!String.IsNullOrEmpty(Debtor.Iban))
            {
                dbtrAcctId.NewElement("IBAN", Debtor.Iban);
            }
            else if (!String.IsNullOrEmpty(Debtor.Other))
            {
                dbtrAcctId.NewElement("Othr").NewElement("Id", Debtor.Other);
            }
            else
            {
                throw new Exception("Need either IBAN or Other>Id for DbtrAcct.");
            }
            dbtrAcct.NewElement("Ccy", DebtorAccountCurrency);

            var finInstnId = pmtInf.NewElement("DbtrAgt").NewElement("FinInstnId");

            finInstnId.NewElement("BIC", Debtor.Bic);
            if (Debtor.AgentAddress != null)
            {
                XmlUtils.AddPostalAddressElements(finInstnId, Debtor.AgentAddress);
            }

            if (IsInternational)
            {
                pmtInf.NewElement("ChrgBr", SepaChargeBearerUtils.SepaChargeBearerToString(ChargeBearer));
            }
            else
            {
                pmtInf.NewElement("ChrgBr", "SLEV");
            }

            // Part 3: Credit Transfer Transaction Information
            foreach (var transfer in transactions)
            {
                GenerateTransaction(pmtInf, transfer);
            }

            return(xml);
        }
        /// <summary>
        /// Generate a Payment Information node for a Sequence Type.
        /// </summary>
        /// <param name="xml">The XML object to write</param>
        /// <param name="sqType">The Sequence Type</param>
        /// <param name="seqTransactions">The transactions of the specified type</param>
        private XmlElement GeneratePaymentInformation(XmlDocument xml, SepaSequenceType sqType, IEnumerable <SepaDebitTransferTransaction> seqTransactions)
        {
            int     controlNumber = 0;
            decimal controlSum    = 0;

            // We check the number of transaction to write and the sum due to the Sequence Type.
            foreach (var transfer in seqTransactions)
            {
                controlNumber += 1;
                controlSum    += transfer.Amount;
            }

            // If there is no transaction, we end the method here.
            if (controlNumber == 0)
            {
                return(null);
            }

            var pmtInf = XmlUtils.GetFirstElement(xml, "CstmrDrctDbtInitn").NewElement("PmtInf");

            pmtInf.NewElement("PmtInfId", PaymentInfoId ?? MessageIdentification);
            if (CategoryPurposeCode != null)
            {
                pmtInf.NewElement("CtgyPurp").NewElement("Cd", CategoryPurposeCode);
            }

            pmtInf.NewElement("PmtMtd", Constant.DebitTransfertPaymentMethod);
            pmtInf.NewElement("NbOfTxs", controlNumber);
            pmtInf.NewElement("CtrlSum", StringUtils.FormatAmount(controlSum));

            var pmtTpInf = pmtInf.NewElement("PmtTpInf");

            pmtTpInf.NewElement("SvcLvl").NewElement("Cd", "SEPA");
            pmtTpInf.NewElement("LclInstrm").NewElement("Cd", LocalInstrumentCode);
            pmtTpInf.NewElement("SeqTp", SepaSequenceTypeUtils.SepaSequenceTypeToString(sqType));

            pmtInf.NewElement("ReqdColltnDt", StringUtils.FormatDate(RequestedExecutionDate));
            pmtInf.NewElement("Cdtr").NewElement("Nm", Creditor.Name);

            var cdtrAcct = pmtInf.NewElement("CdtrAcct");

            cdtrAcct.NewElement("Id").NewElement("IBAN", Creditor.Iban);
            cdtrAcct.NewElement("Ccy", CreditorAccountCurrency);

            var finInstnId = pmtInf.NewElement("CdtrAgt").NewElement("FinInstnId");

            finInstnId.NewElement("BIC", Creditor.Bic);
            if (Creditor.AgentAddress != null)
            {
                XmlUtils.AddPostalAddressElements(finInstnId, Creditor.AgentAddress);
            }
            pmtInf.NewElement("ChrgBr", "SLEV");

            var othr = pmtInf.NewElement("CdtrSchmeId").NewElement("Id")
                       .NewElement("PrvtId")
                       .NewElement("Othr");

            othr.NewElement("Id", PersonId);
            othr.NewElement("SchmeNm").NewElement("Prtry", "SEPA");

            return(pmtInf);
        }