Mike U
Mike U

Reputation: 3061

How do I use Linq to read XML

I have the following XML

<Transaction><TransactionID>1559183866</TransactionID><Email>[email protected]</Email><Frequency>Yearly</Frequency><Amount>10</Amount><Status>1</Status><CreateDate>2/7/2012 8:29:43 AM</CreateDate></Transaction>

I am trying to use link to create an object to reference the contents

XDocument result = XDocument.Load(readStream);

var detail = (from x in result.Descendants("transaction")
              select new {
                  TransactionID = x.Element("transactionid").Value,
                  Frequency = x.Element("frequency").Value,
                  Amount = x.Element("amount").Value,
                  Email = x.Element("email").Value,
                  Status = x.Element("status").Value
              }).First();

But keep getting an Exception Sequence contains no Elements.

Any idea what I am doing wrong?

Thanks

Upvotes: 1

Views: 206

Answers (3)

Sofian Hnaide
Sofian Hnaide

Reputation: 2364

Matching elements is a case-sensitive operation.

eg. "Transaction" != "transaction"

Try this instead:

var detail = (from x in result.Descendants("Transaction") 
                          select new { 
                              TransactionID = x.Element("TransactionID").Value, 
                              Frequency =  x.Element("Frequency").Value,
                              Amount = x.Element("Amount").Value, 
                              Email = x.Element("Email").Value,
                              Status = x.Element("Status").Value })
                              .First();

Upvotes: 4

veblock
veblock

Reputation: 1924

Given your XML you should change this line [EDIT: given your XML use Jon's answer]

var detail = (from x in result.Descendants("Transaction")

to

var detail = (from x in result.Element("Transaction")

That will prevent any nested Transaction elements to be included in the result. Obviously you've got the casing problem too.

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1503220

If that's the whole of the XML, then you're making life more complicated than you need to. The Transaction element is the root element, and you know there'll be exactly one:

XDocument result = XDocument.Load("test.xml");

// Just for brevity
var x = result.Root;
var detail = new {
          // Note the fixed capitalization
          TransactionID = x.Element("TransactionID").Value,
          Frequency = x.Element("Frequency").Value,
          Amount = x.Element("Amount").Value,
          Email = x.Element("Email").Value,
          Status = x.Element("Status").Value
      };
Console.WriteLine(detail);

Of course, if this is part of a larger document, then you could use:

var x = result.Descendants("Transaction").First();
// Same as before

You might want to consider using the explicit conversions from XElement to various other types, by the way. For example:

var detail = new {
          // Note the fixed capitalization
          TransactionID = (string) x.Element("TransactionID"),
          Frequency = (string) x.Element("Frequency"),
          Amount = (int) x.Element("Amount"),
          Email = (string) x.Element("Email"),
          Status = (int) x.Element("Status")
      };

Note that any casts to nullable types (either reference types or nullable value types) will simply return null if the input is null, so a missing element would end up giving you a null result. Sometimes that's a good thing; other times you really want an exception.

Upvotes: 4

Related Questions