0

I'm trying to work with LINQ to XML to parse the notifications I'm getting from Google Checkout.

The response is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<authorization-amount-notification xmlns="http://checkout.google.com/schema/2" serial-number="153286076708098-00005-6">
 <authorization-amount currency="USD">60.0</authorization-amount>
 <authorization-expiration-date>2011-07-03T21:27:48.000Z</authorization-expiration-date>
 <avs-response>Y</avs-response>
 <cvn-response>M</cvn-response>
 <timestamp>2011-06-26T21:28:48.741Z</timestamp>
 <google-order-number>153286076708098</google-order-number>
 <order-summary>
   <total-chargeback-amount currency="USD">0.0</total-chargeback-amount>
   <google-order-number>153286076708098</google-order-number>
   <total-charge-amount currency="USD">0.0</total-charge-amount>
   <total-refund-amount currency="USD">0.0</total-refund-amount>
   <risk-information>
     <ip-address>77.42.229.34</ip-address>
     <billing-address>
       <address1>somewhere in Beirut</address1>
       <address2></address2>
       <phone>70892555</phone>
       <email>[email protected]</email>
       <contact-name>Fisharwe User</contact-name>
       <company-name></company-name>
       <fax></fax>
       <country-code>LB</country-code>
       <city>Beirut</city>
       <region></region>
       <postal-code>1000</postal-code>
     </billing-address>
     <avs-response>Y</avs-response>
     <cvn-response>M</cvn-response>
     <eligible-for-protection>true</eligible-for-protection>
     <partial-cc-number>1111</partial-cc-number>
     <buyer-account-age>18</buyer-account-age>
   </risk-information>
   <authorization>
     <authorization-amount currency="USD">60.0</authorization-amount>
     <authorization-expiration-date>2011-07-03T21:27:48.000Z</authorization-expiration-date>
   </authorization>
   <purchase-date>2011-06-26T21:27:48.000Z</purchase-date>
   <archived>false</archived>
   <shopping-cart>
     <items>
       <item>
         <item-name>Credits</item-name>
         <item-description>Description</item-description>
         <unit-price currency="USD">60.0</unit-price>
         <quantity>1</quantity>
       </item>
     </items>
   </shopping-cart>
   <order-adjustment>
     <merchant-codes />
     <total-tax currency="USD">0.0</total-tax>
     <adjustment-total currency="USD">0.0</adjustment-total>
   </order-adjustment>
   <promotions />
   <buyer-id>975104325298289</buyer-id>
   <buyer-marketing-preferences>
     <email-allowed>false</email-allowed>
   </buyer-marketing-preferences>
   <buyer-shipping-address>
     <address1>somewhere in Beirut</address1>
     <address2></address2>
     <phone>70892555</phone>
     <email>[email protected]</email>
     <contact-name>Fisharwe User</contact-name>
     <company-name></company-name>
     <fax></fax>
     <structured-name>
       <first-name>Fisharwe</first-name>
       <last-name>User</last-name>
     </structured-name>
     <country-code>LB</country-code>
     <city>Beirut</city>
     <region></region>
     <postal-code>1000</postal-code>
   </buyer-shipping-address>
   <order-total currency="USD">60.0</order-total>
   <fulfillment-order-state>NEW</fulfillment-order-state>
   <financial-order-state>CHARGEABLE</financial-order-state>
 </order-summary>
</authorization-amount-notification>

Here's the code I'm using:

        var serverResponse = _checkoutService.Post(data, GoogleCheckoutConstants.ReportsUri);
        var xmlData = XDocument.Parse(serverResponse);
        bool charged = false;
        if(xmlData.Root.Name.Equals("authorization-amount-notification"))
        {

            var amount = (from c in xmlData.Elements()
                          where c.Name.Equals("authorization-amount")
                          select c).First().Value;
            var googleNumber = (from c in xmlData.Elements()
                                where c.Name.Equals("google-order-number")
                                select c).First().Value;
            _checkoutService.ChargeAndShip(googleNumber, amount);
            charged = true;
        }

This is the first time I use LINQ to XML, so I'm not really sure what's wrong with my code. But it's not even going inside the if statement. So when I replace the condition with:

if (serverResponse.IndexOf("authorization-amount-notification") > -1)

I end up getting errors telling me that the amount and googleNumber were not found.

Any suggestions?

6
  • Where is the closing tag for new-order-notification ? Commented Jun 27, 2011 at 11:13
  • Maybe you have query with xmlData.Elements("authorization-amount") Commented Jun 27, 2011 at 11:13
  • 1
    Does the XML use Namespaces? You may need to add them into the query : stackoverflow.com/questions/2340411/…. Also try examining the elements using Quick Watch and see what they say. Commented Jun 27, 2011 at 11:14
  • 1
    Actually, it seems the response XML has been truncated. I dont see authorization-amount or authorization-amount-notification. Commented Jun 27, 2011 at 11:15
  • You will have use XNamespace and append the same when you query for elements and by the way where is the root ? Commented Jun 27, 2011 at 11:20

2 Answers 2

2

You need to put the namespace in to the Xml, and you the Elements are SubElements of the Root Node.

You are only after one Element so doing Elements() then .First() is pointless. Just do Element() instead.

Also, you can match element names by passing in the Name of the Element + namespace to the Element() method.

var xmlData = XDocument.Parse(xml);

XNamespace ns = "http://checkout.google.com/schema/2";

if (xmlData.Root.Name == ns + "authorization-amount-notification")
{ 
    var amount = 
        xmlData
        .Root
        .Element(ns + "authorization-amount")
        .Value;

    var googleNumber = 
        xmlData
        .Root
        .Element(ns + "google-order-number")
        .Value;  
    _checkoutService.ChargeAndShip(googleNumber, amount);             

    charged = true;
}
Sign up to request clarification or add additional context in comments.

5 Comments

@DaveShaw: I'm still getting the same error Sequence contains no elements
@Kassem, sorry, I didn't run it. I have fixed the code above. The Elements are under the Root node, so you needed to So Root.Element.
@DaveShaw: How do you get to nodes that are not direct children of the root? I tried username = xmlData.Root.Element(ns + "shopping-cart").Element(ns + "merchant-private-data").Value; but it did not work for me... Any ideas?
You are missing a step in the hierarchy, you need to go down each element from the root: xmlData.Root.Element(ns + "order-summary").Element(ns + "shopping-cart").Elements(ns + "items");
If you grab yourself a copy of LinqPad you can use the .Dump() extension method to debug what's going wrong... When I get stuck with my L2Xml I just move up a few levels and see what's there and where I am going wrong. That's the tool I used for debugging your issue.
0

What about...

if(xmlData.Root.Name.LocalName.Equals("new-order-notification")){
 .... 
}

But the xml you posted doesn't seem to match the code your using.. The elements do not exist

1 Comment

I fixed my post. I copied the wrong XML block, now I've got the right one in my post. Sorry about that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.