0

I am pulling XML data from a server using an API and use LINQ to store the results in an anonymous object list, however some of the data is returning "null" and I figured it must be due to the XML document heirarchy. See below-

<export type="orderexport" date="13/01/2015" time="5:01:18 PM">
  <order>
    <OrderNumber>149612</OrderNumber>
    <CustomerNumber>146538</CustomerNumber>
    <Currency>AUD</Currency>
    <Locale>en_AU</Locale>
    <GrandTotal>1548.98</GrandTotal>
    <TotalBeforeTax>1411.58</TotalBeforeTax>
    <TotalTax>137.4</TotalTax>
    <Addresses>
      <BillingAddress>
        <Email>XXXXXX@XXXXXXX.com.au</Email>
      </BillingAddress>
      <ShippingAddress>
        <Email>XXXXXX@XXXXXXX.com.au</Email>
      </ShippingAddress>
    </Addresses>
    <LineItems>
      <LineItem>...</LineItem>
      <LineItemSalesDiscount>...</LineItemSalesDiscount>
      <LineItemDiscount>...</LineItemDiscount>
      <LineItemShipping>...</LineItemShipping>
      <LineItemPayment>...</LineItemPayment>
      <LineItemPaymentDiscount>...</LineItemPaymentDiscount>
    </LineItems>
    <CreationDate>13/01/2015 9:42:59 AM</CreationDate>
    <ViewedOn>13/01/2015 9:44:20 AM</ViewedOn>
    <cancelledon/>
    <readyforshippingon>13/01/2015 1:58:41 PM</readyforshippingon>
    <paidon>13/01/2015 9:43:15 AM</paidon>
    <ordercomment>
      removed
    </ordercomment>
  </order>
</export>

I can pull all the elements fine at the first level, however I need to include the tag but it is nested under another level, when I try to get its value like I get the rest of it I get a null value.

        //Create Request
        myHttpWebRequest = (HttpWebRequest)HttpWebRequest.Create(URL);
        myHttpWebRequest.Method = "GET";
        myHttpWebRequest.ContentType = "text/xml; encoding='utf-8'";

        //Get Response
        myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();

        //Load response stream into XMLReader
        myXMLReader = new XmlTextReader(myHttpWebResponse.GetResponseStream());

        var xdoc = XDocument.Load(myXMLReader);

        var result = from x in xdoc.Root.Elements()
                     select new
                     {
                         OrderNumber = (string)x.Element("OrderNumber"),
                         CustomerNumber = (string)x.Element("CustomerNumber"),
                         GrandTotal = (double)x.Element("GrandTotal"),
                         Email = (string)x.Element("Email")
                     };

OUTPUT: "{ OrderNumber = "149612", CustomerNumber = "146538", GrandTotal = 1548.98, Email = null }"

I have never read an XML document before but I'm fairly sure the above code is right, I'm sure I just need to change the LINQ expression line for Email but I don't know what it should be.

Regards

Rahul Singh
  • 21,585
  • 6
  • 41
  • 56
Aaron McKelvie
  • 167
  • 4
  • 17

2 Answers2

1

Since Email is present inside Addresses\BillingAddress, You need to extract email like this:-

Email = x.Descendants("BillingAddress")
         .Select(e => (string)e.Element("Email")).FirstOrDefault()

Please note, I am only fetching the Email address present inside BillingAddress node, if you want Email address present inside ShippingAddress node you can do it like this:-

Email = x.Descendants("ShippingAddress")
             .Select(e => (string)e.Element("Email")).FirstOrDefault();
Rahul Singh
  • 21,585
  • 6
  • 41
  • 56
  • Thanks that worked perfectly, can the .Descendants() method be used to go even deeper than one level? Also I have never used FirstOrDefault(), is it recommended to always include? – Aaron McKelvie Jan 13 '15 at 07:12
  • 1
    @AaronMcKelvie - Yes you can, that's why i directly used `BillingAddress` instead of `Addresses\BillingAddress`. Check its definition here: http://www.tizag.com/xmlTutorial/xmldescendant.php. Also, `FirstOrDefault` is used to fetch the first element in the collection otherwise it will return `List` – Rahul Singh Jan 13 '15 at 07:19
0

You can try the easy way. As you already know the XML structure returned by your API,

  1. Create an 'Order' class with similar structure.
  2. Save your XML data to a temporary file.
  3. Use XmlSerializer to Deserialize your XML file and cast it to 'Order' type.
  4. Now you can access all data from object properties.

This link shows exactly how to do that.

Community
  • 1
  • 1
Mahesh4b7
  • 56
  • 5