-1

I have following xml data.

<?xml version="1.0" encoding="utf-8" ?>
<mail>
  <id>signUpConfirmation</id>
  <subject>Activation</subject>
  <body>
Hi, You account is activated \nRegards
</body>
</mail>

I need to read value from <body> tag depending on id I pass.

This is what I have tried

var xml = File.ReadAllText("C:\\Users\\DELL\\Documents\\Visual Studio 2012\\Projects\\Website\\Website\\Files\\Mails.xml");

var str = XElement.Parse(xml);
var result = from mail in str.Elements("mail")
             where (string)mail.Element("id") == "signUpConfirmation"
             select (string)mail.Element("body");
log.Debug("mail data:" + result.First());

I get error :

Sequence contains no elements.

Also, I want to access the value of id tag as well in the same query.

Mr Lister
  • 45,515
  • 15
  • 108
  • 150
Dheeraj Kumar
  • 3,917
  • 8
  • 43
  • 80
  • `id` and `body` are not attributes. Use `.Element`. – Jeroen Mostert Oct 26 '16 at 07:34
  • made the changes. still same error. Question is updated. – Dheeraj Kumar Oct 26 '16 at 07:36
  • You should probably be using [XDocument.Load()](https://msdn.microsoft.com/en-us/library/system.xml.linq.xdocument.load.aspx), rather than parsing a string. – Tieson T. Oct 26 '16 at 07:36
  • ...and if you don't understand why a LINQ query yields no results, break it up into pieces and inspect them. Otherwise you could take forever figuring out that `Elements("mail")` won't work either. – Jeroen Mostert Oct 26 '16 at 07:36
  • Why someone would downvote this question. Even though it has been asked many times, I didnt find any solution to my issue. – Dheeraj Kumar Oct 26 '16 at 07:36
  • Possible duplicate of [LINQ to read XML](http://stackoverflow.com/questions/670563/linq-to-read-xml) – Tieson T. Oct 26 '16 at 07:38
  • @ Tieson. I googled since morning to solve my problem and asked this question only after all my efforts. link you provided.. didnt work for my issue. – Dheeraj Kumar Oct 26 '16 at 07:41

2 Answers2

5

You have a couple of problems:

  1. The id and body are not attributes but elements so you need to use the .Elements
  2. You are using the XElement to parse the xml. It will start from the first element which is mail and then you are looking for child elements of it with the name of mail - which non exist. Use XDocument.

Code:

var result = (from mail in XDocument.Load("data.xml").Descendants("mail")
              where mail.Element("id").Value == "signUpConfirmation"
              select new {
                  Body = mail.Element("body").Value,
                  Subject = mail.Element("subject").Value
              }).ToList();
Gilad Green
  • 36,708
  • 7
  • 61
  • 95
  • @DKR - please consider marking as solved when the 15 minutes pass :) – Gilad Green Oct 26 '16 at 07:40
  • one more thing. what if along with ("body"), i want value of ("subject") as well.. Can we do that with same query, I am sorry for this basic question but I am new to linq. thanks – Dheeraj Kumar Oct 26 '16 at 07:49
  • @DKR - see update :) but please also add this extra requirement to the question – Gilad Green Oct 26 '16 at 07:56
  • I have updated question. thanks. I am using result.First() to access which is giving me a complete string, how do I separate these 2 values.? – Dheeraj Kumar Oct 26 '16 at 08:01
  • 1
    @DKR - it now returns an object with 2 properties so store the result of `.First()` to a variable and then access its `.Body` and `.Subject` – Gilad Green Oct 26 '16 at 08:03
1
var str = XDocument.Parse("<?xml version=\"1.0\" encoding=\"utf-8\" ?><mail>  <id>signUpConfirmation</id>  <subject>Activation</subject>  <body>Hi, You account is activated \nRegards</body></mail>");

var result = from mail in str.Elements("mail")
where (string)mail.Element("id") == "signUpConfirmation"
select mail.Element("body");
result.FirstOrDefault();

Here is the code that work.

XDocument

instead of

XElement

End .Element as @DKR said.