mkautzm
mkautzm

Reputation: 1146

Read specific element out of IEnumerable<XElement>

I have this block of XML:

<Books>
  <BookData id="BookID_100">
    <Name>The Catcher and the Rye</Name>
    <Description>This is a neat book that you might have had to read in school</Description>
    <Date>1/1/1900</Date>
    <IsHardcover>1</IsHardcover>
  </BookData>
  <BookData id="BookID_101">
    <Name>Harry Potter</Name>
    <Description>J.K. Rowlings Fantasy Epic</Description>
    <Date>1/1/2000</Date>
    <IsHardcover>0</IsHardcover>
  </BookData>
</Books>

I'm reading a single 'book' into memory as an IEnumerable:

IEnumerable<XElement> book =
  from el in root.Elements("BookData")
  where (string)el.Attribute("id") == "BookID_100"
  select el;

Now, from here, how do retrieve a value based on the tag? Say, I want the 'Name' data. How do I get a string with the content, "The Catcher and The Rye"? This seems like it should be simple, but I everything I see is extremely esoteric and unwieldly when all I want to do is

// Pseudo Code
string bookName = book.GetElementByID("Name").ToString();

Upvotes: 0

Views: 1689

Answers (2)

maccettura
maccettura

Reputation: 10818

Why are you getting a collection of book elements when you clearly only want the book with the specified ID? If you only want the one book you can just use FirstOrDefault()

Try this instead:

//This will return the first book matching: "BookID_100" or NULL
var book = root.Elements("BookData")
                  .FirstOrDefault(x => x.Attribute("id") == "BookID_100");

//'name' will be null if book or name is null, or the name of the book element
string name = book?.Element("Name")?.Value;

If you are not using C#6 or above then the ?. operator will not be available to you, in that case just check for null like usual:

string name = string.Empty;
if(book != null && book.Element("Name") != null)
{ 
    name = book.Element("Name").Value;
}

Upvotes: 3

Ehsan Sajjad
Ehsan Sajjad

Reputation: 62488

You will have to call Element method and pass the element name of which you want to get from the XElement:

IEnumerable<XElement> book =
  from el in root.Elements("BookData")
  where el.Attribute("id").Value == "BookID_100"
  select el.Element("Name");

This will return you only the element Name of your Node. You can further call .Value property to get the text between the opening and closing tag of Name tag.

If you need only single book as it looks like you will get one book back against an id you would need to write:

var book =
      (from el in root.Elements("BookData")
       where el.Attribute("id").Value == "BookID_100"
       select el).FirstOrDefault();

 if(book !=null)
 {
    string Name  = book.Element("Name").Value;
 }

Upvotes: 2

Related Questions