简体   繁体   中英

How to Create complex XML structure in C#

In my application, i have to work with the PayGate API for processing online payment.

The requests must be in the following format:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Header/>
    <SOAP-ENV:Body>
        <SinglePaymentRequest xmlns="http://www.paygate.co.za/PayHOST">
            <CardPaymentRequest>
                <Account>
                    <PayGateId>10011072130</PayGateId>
                    <Password>test</Password>
                </Account>
                <Customer>
                    <Title>Mr</Title>
                    <FirstName>Joe</FirstName>
                    <LastName>Soap</LastName>
                    <Telephone>0861234567</Telephone>
                    <Mobile>0735552233</Mobile>
                    <Email>joe@soap.com</Email>
                </Customer>
                <CardNumber>4000000000000002</CardNumber>
                <CardExpiryDate>122020</CardExpiryDate>
                <CVV>999</CVV>
                <BudgetPeriod>0</BudgetPeriod>
                <Redirect>
                    <NotifyUrl>https://www.mytestsite.com/notify</NotifyUrl>
                    <ReturnUrl>https://www.mytestsite.com/return</ReturnUrl>
                </Redirect>
                <Order>
                    <MerchantOrderId>INV101</MerchantOrderId>
                    <Currency>ZAR</Currency>
                    <Amount>100</Amount>
                </Order>
            </CardPaymentRequest>
        </SinglePaymentRequest>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

I am trying to create this structure using XElement classes in C#, but every tag which holds the words: "SOAP-ENV:" before them, dont get parsed right.

This is my function:

        private string ParseCardRequestToXml()
        {
            XNamespace soapEnv = "SOAP-ENV";
            XNamespace spReq = "http://www.paygate.co.za/PayHOST";

            //Envelope
            XElement xmlEnvlelope = new XElement(soapEnv + "Envelope", new XAttribute(XNamespace.Xmlns + "SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"));

            //Header
            XElement xmlHeader = new XElement(soapEnv + "Header");

            //Body element
            XElement xmlBody = new XElement("Body");

            //SinglePaymentRequest
            XElement xmlSinglePaymentRequest = new XElement(spReq + "SinglePaymentRequest");

            //CardPaymentRequest
            XElement xmlCardPaymentRequest = new XElement("CardPaymentRequest");

            //Account
            XElement xmlAccount = new XElement("Account");

            xmlAccount.Add(new XElement("PayGateId", "10011072130"));
            xmlAccount.Add(new XElement("Password", "test"));

            //Add account to "CardPaymentRequest" tag
            xmlCardPaymentRequest.Add(xmlAccount);

            //Customer
            XElement xmlCustomer = new XElement("Customer");

            xmlCustomer.Add(new XElement("Title", "Mr"));
            xmlCustomer.Add(new XElement("FirstName", "Joe"));
            xmlCustomer.Add(new XElement("LastName", "Soap"));
            xmlCustomer.Add(new XElement("Telephone", "0861234567"));
            xmlCustomer.Add(new XElement("Mobile", "0735552233"));
            xmlCustomer.Add(new XElement("Email", "joe@soap.com"));

            //Add customer to "CardPaymentRequest" tag
            xmlCardPaymentRequest.Add(xmlCustomer);

            //Add Card info to "CardPaymentRequest" tag
            xmlCardPaymentRequest.Add(new XElement("CardNumber", "4000000000000002"));
            xmlCardPaymentRequest.Add(new XElement("CardExpiryDate", "122020"));
            xmlCardPaymentRequest.Add(new XElement("CVV", 999));
            xmlCardPaymentRequest.Add(new XElement("BudgetPeriod", 0));

            //Redirect
            XElement xmlRedirect = new XElement("Redirect");

            xmlRedirect.Add(new XElement("NotifyUrl", "https://www.mytestsite.com/notify"));
            xmlRedirect.Add(new XElement("ReturnUrl", "https://www.mytestsite.com/return"));

            //Add redirect to "CardPaymentRequest" tag
            xmlCardPaymentRequest.Add(xmlRedirect);

            //Order
            XElement xmlOrder = new XElement("Order");

            xmlOrder.Add(new XElement("MerchantOrderId", "INV101"));
            xmlOrder.Add(new XElement("Currency", "ZAR"));
            xmlOrder.Add(new XElement("Amount", 100));

            //Add order to "CardPaymentRequest" tag
            xmlCardPaymentRequest.Add(xmlOrder);

            xmlSinglePaymentRequest.Add(xmlCardPaymentRequest);

            xmlBody.Add(xmlSinglePaymentRequest);

            xmlEnvlelope.Add(xmlHeader);
            xmlEnvlelope.Add(xmlBody);

            return xmlEnvlelope.ToString();
        }

And this is the result i get:

<Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns=\"SOAP-ENV\">
  <Header />
  <Body xmlns=\"\">
    <SinglePaymentRequest xmlns=\"http://www.paygate.co.za/PayHOST\">
      <CardPaymentRequest xmlns=\"\">
        <Account>
          <PayGateId>10011072130</PayGateId>
          <Password>test</Password>
        </Account>
        <Customer>
          <Title></Title>
          <FirstName>Joe</FirstName>
          <LastName>Soap</LastName>
          <Telephone>0861234567</Telephone>
          <Mobile>0735552233</Mobile>
          <Email>joe@soap.com</Email>
        </Customer>
        <CardNumber>4000000000000002</CardNumber>
        <CardExpiryDate>122020</CardExpiryDate>
        <CVV>999</CVV>
        <BudgetPeriod>0</BudgetPeriod>
        <Redirect>
          <NotifyUrl>https://www.mytestsite.com/notify</NotifyUrl>
          <ReturnUrl>https://www.mytestsite.com/return</ReturnUrl>
        </Redirect>
        <Order>
          <MerchantOrderId>INV101</MerchantOrderId>
          <Currency>ZAR</Currency>
          <Amount>100</Amount>
        </Order>
      </CardPaymentRequest>
    </SinglePaymentRequest>
  </Body>
</Envelope>

I used the XNamespace class according to this guide from Microsoft but i seem to have missed something. Edit: In the example the make variable XNamespace aw but in my case i cannot create such variable because "-" is not allowed to be used in naming...

Edit 2: Ok so i went and tried to build the request using StringBuilder.

This is the function:

        private string GetDemoCardRequestXML()
        {
            StringBuilder builder = new StringBuilder();

            builder.Append("<SOAP-ENV:Envelope xmlns:SOAP-ENV=").Append('"').Append("http://schemas.xmlsoap.org/soap/envelope/").Append('"').Append(">");
            builder.Append("<SOAP-ENV:Header/>");
            builder.Append("<SOAP-ENV:Body>");
            builder.Append("<SinglePaymentRequest xmlns=").Append('"').Append("http://www.paygate.co.za/PayHOST").Append('"').Append(">");
            builder.Append("<CardPaymentRequest>");
            builder.Append("<Account>");
            builder.Append("<PayGateId>").Append("10011072130").Append("</PayGateId>");
            builder.Append("<Password>").Append("test").Append("</Password>");
            builder.Append("</Account>");
            builder.Append("<Customer>");
            builder.Append("<Title>").Append("Mr").Append("</Title>");
            builder.Append("<FirstName>").Append("Joe").Append("</FirstName>");
            builder.Append("<LastName>").Append("Soap").Append("</LastName>");
            builder.Append("<Telephone>").Append("0861234567").Append("</Telephone>");
            builder.Append("<Mobile>").Append("0735552233").Append("</Mobile>");
            builder.Append("<Email>").Append("joe@soap.com").Append("</Email>");
            builder.Append("</Customer>");
            builder.Append("<CardNumber>").Append("4000000000000002").Append("</CardNumber>");
            builder.Append("<CardExpiryDate>").Append("122020").Append("</CardExpiryDate>");
            builder.Append("<CVV>").Append("999").Append("</CVV>");
            builder.Append("<BudgetPeriod>").Append("0").Append("</BudgetPeriod>");
            builder.Append("<Redirect>");
            builder.Append("<NotifyUrl>").Append("https://www.mytestsite.com/notify").Append("</NotifyUrl>");
            builder.Append("<ReturnUrl>").Append("https://www.mytestsite.com/return").Append("</ReturnUrl>");
            builder.Append("</Redirect>");
            builder.Append("<Order>");
            builder.Append("<MerchantOrderId>").Append("INV101").Append("</MerchantOrderId>");
            builder.Append("<Currency>").Append("ZAR").Append("</Currency>");
            builder.Append("<Amount>").Append("100").Append("</Amount>");
            builder.Append("</Order>");
            builder.Append("</CardPaymentRequest>");
            builder.Append("</SinglePaymentRequest>");
            builder.Append("</SOAP-ENV:Body>");
            builder.Append("</SOAP-ENV:Envelope>");

            return builder.ToString();
        }

Result:

<SOAP-ENV:Envelope
    xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">
    <SOAP-ENV:Header/>
    <SOAP-ENV:Body>
        <SinglePaymentRequest
            xmlns=\"http://www.paygate.co.za/PayHOST\">
            <CardPaymentRequest>
                <Account>
                    <PayGateId>10011072130</PayGateId>
                    <Password>test</Password>
                </Account>
                <Customer>
                    <Title>Mr</Title>
                    <FirstName>Joe</FirstName>
                    <LastName>Soap</LastName>
                    <Telephone>0861234567</Telephone>
                    <Mobile>0735552233</Mobile>
                    <Email>joe@soap.com</Email>
                </Customer>
                <CardNumber>4000000000000002</CardNumber>
                <CardExpiryDate>122020</CardExpiryDate>
                <CVV>999</CVV>
                <BudgetPeriod>0</BudgetPeriod>
                <Redirect>
                    <NotifyUrl>https://www.mytestsite.com/notify</NotifyUrl>
                    <ReturnUrl>https://www.mytestsite.com/return</ReturnUrl>
                </Redirect>
                <Order>
                    <MerchantOrderId>INV101</MerchantOrderId>
                    <Currency>ZAR</Currency>
                    <Amount>100</Amount>
                </Order>
            </CardPaymentRequest>
        </SinglePaymentRequest>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Now the request looks better, but the escaping characters "\" in the xmlns url area are preventing from it to be a valid XML. Any idea how i can remove those?

You have to use soapEnv.NamespaceName to append the prefix to XmlElement

As I wrote in my first comment, you need add namespaces soapEnv to "Body" and spReq to all elements starting from "CardPaymentRequest"

it will produces XML like

<Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns="SOAP-ENV">
  <Header />
  <Body>
    <SinglePaymentRequest xmlns="http://www.paygate.co.za/PayHOST">
      <CardPaymentRequest>
       ...
      </CardPaymentRequest>
    </SinglePaymentRequest>
  </Body>
</Envelope>

Unfortunately, I was wrong, and this is not formally the same xml and will not pass check against same schema.

To get excat xml you have to change soapEnv to http://schemas.xmlsoap.org/soap/envelope/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM