Buck Hicks
Buck Hicks

Reputation: 1574

Why is this LINQ not finding an element two levels down?

I am having trouble parsing the XML file (stripped down sample of XML in code snippet below). The error I am getting is

An unhandled exception of type 'System.NullReferenceException' occurred in XmlToLink.exe Additional information: Object reference not set to an instance of an object.

I know my issue is in the XmlBarcodes = el.Element("Barcodes") area because when I comment that section out the Order Number, First & Last Name, and the ProductName are returned. I think it is because I am not drilling down to the BarcodeString correctly with LINQ but I have tried every variation of getting to that element that I could come up with so I am wondering if there is something else (not obvious to me) that is wrong with the syntax. What am I doing wrong?

    private static IEnumerable<XmlOrders> ParseXml()
    {            
        XDocument document = XDocument.Parse(GetXml());
        var query = from el in document.Root.Elements("Order")
                    select new XmlOrders
                    {
                        Id = (int)el.Element("Id"),
                        XmlBillingAddress = new XmlBillingAddress()
                        {
                            FirstName = (string)el.Element("BillingAddress").Element("FirstName"),
                            LastName = (string)el.Element("BillingAddress").Element("LastName"),
                        },

                        XmlOrderItems = el.Element("OrderItems")
                        .Elements("OrderItem")
                        .Select(orderItem => new XmlOrderItems()
                        {
                            ProductName = (string)orderItem.Element("ProductName")
                        }).ToList(),

                        //XmlBarcodes = el.Element("OrderItems").Element("OrderItem").Element("Barcodes")
                        XmlBarcodes = el.Element("Barcodes")
                        .Elements("Barcode")
                        .Select(barcode => new XmlBarcodes()
                        {
                            BarcodeNumber = (string)barcode.Element("CodeString")
                        }).ToList()
                    };

        return query;
    }

    private static String GetXml()
    {
        return @"<ArrayOfOrder>
          <Order>
            <Id>25057</Id>
            <OrderGuid />
            <BillingAddress>
              <FirstName>Alex</FirstName>
              <LastName>Onetime</LastName>
            </BillingAddress>
            <OrderItems>
              <OrderItem>
                <ProductName>High Mileage Oil Change</ProductName>
                <Barcodes>
                  <Barcode>
                    <CodeString>A5834A7</CodeString>
                  </Barcode>
                </Barcodes>
              </OrderItem>
            </OrderItems>
           </Order>
          <Order>
            <Id>25058</Id>
            <OrderGuid />
            <BillingAddress>
              <FirstName>Christopher</FirstName>
              <LastName>Tracey</LastName>
            </BillingAddress>
            <OrderItems>
              <OrderItem>
                <ProductName>Conventional Oil Change</ProductName>
                <Barcodes>
                  <Barcode>
                    <CodeString>A7E32B3</CodeString>
                  </Barcode>
                  <Barcode>
                    <CodeString>A6F73BA</CodeString>
                  </Barcode>
                </Barcodes>
              </OrderItem>
            </OrderItems>
           </Order>
        </ArrayOfOrder>";
    }

An unhandled exception of type 'System.NullReferenceException' occurred in XmlToLink.exe

Additional information: Object reference not set to an instance of an object.

Upvotes: 0

Views: 166

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1501646

As you say, you're not drilling down to the Barcodes element under OrderItem. Don't forget that el will refer to an Order element, but you want the Order -> OrderItems -> OrderItem -> Barcodes -> Barcode element. I suspect you want:

XmlBarcodes = el.Element("OrderItems")
                .Elements("OrderItem")
                .Elements("Barcodes")
                .Elements("Barcode")
                .Select(barcode => new XmlBarcodes {
                     BarcodeNumber = (string) barcode.Element("CodeString")
                })
                .ToList()

However, given that this is really part of an OrderItem, you should perhaps change your XmlOrderItems class to include the barcodes.

(As an aside, it seems odd that your classnames are plural - each XmlBarcodes object is only one barcode, right?)

Upvotes: 1

Related Questions