Xml – Explain the LINQ to XML for a beginner below

linq-to-xml

Can someone explain the LINQ to XML below? Also, what is the correct way to check if the method returned a List with Data? Do you just check if the List is empty.

Code:

public List<Listing> GetList()
{
    if (File.Exists(this.xmlFilePath))
    {
        XDocument doc = XDocument.Load(this.xmlFilePath);

        var listings = from row in doc.Root.Elements("listing")
                       select new Listing
                       {
                           A = (string)row.Element("A"),
                           B = (string)row.Element("B"),
                           C = (string)row.Element("C"),
                           D = (string)row.Element("D"),
                           E = (string)row.Element("E")
                       };

        return listings.ToList();
    }
    else
    {
        return new List<Listing>();
    }
}

XML:

<Listings>
   <listing>
     <a>A</a>
     <b>B</b>
     <c>C</c>
     <d>D</d>
     <e>E</e>
    </listing>
    <listing>
     <a>F</a>
     <b>G</b>
     <c>C</c>
     <d>H</d>
     <e>I</e>
    </listing>
</Listings>

Best Solution

You can check if listings has any data by examining the result of the Count() method on the listings variable, and to answer the question asked in the comments section below, "So, there is no way to actually return null? I have to return a List<listing>() object?", please see the following code:

public List<Listing> GetList()
{
  if (File.Exists(this.xmlFilePath))
  {
    XDocument doc = XDocument.Load(this.xmlFilePath);

    var listings = from row in doc.Root.Elements("listing")
             select new Listing
             {
               A = (string)row.Element("A"),
               B = (string)row.Element("B"),
               C = (string)row.Element("C"),
               D = (string)row.Element("D"),
               E = (string)row.Element("E")
             };

    // Check if we have any matches         
    if(listings.Count() > 0)
    {
      return listings.ToList();
    }

    return null;
  }
  return null;
}

I think that's what you're after.

There isn't much to explain about how the code works. In the first part of the query:

var listings = from row in doc.Root.Elements("listing")

The expression doc.Root.Elements("listing") selects all of the <listing> elements below the document root (<Listings>).

The second part of the query creates a new Listing object for each <listing> element and assigns the inner text of each of the A,B,C,D and E child elements to each of the A,B,C,D and E properties of each new Listing object created.

The line containing: return listings.ToList(); returns a generic List<T> of Listing objects.

Using the sample XML provided, you'll find that each Listing object's A,B,C,D, and E properties will be null. This is because the character case of each of the row.Element() selectors is different from the XML being queried, i.e. your XML has <a> and row.Element("A") uses an uppercase 'A'. XML node matching in LINQ to XML is case-sensitive.

Related Question