views:

260

answers:

3

I have following xml which same child element (Filed) and I want to get value from each Child element.

Sameple XML

 <root xmlns="">
    <books cat="F1" ISBN="01F187597" genre="Programming">
      <Field name="Title" val="XML" /> 
      <Field name="Publish Date" val="20010424" /> 
      <Field name="Price" val="43.00" /> 
    </books>
 </root>

Code

  XDocument xdoc = XDocument.Load("c:\\test6.xml");

  var booksData = from book in xdoc.Descendants("root")
                  //I guess create this and do something with it
                  // let fieldElements = book.Descendants("Field")
                  select new Book
                  {
                         cat = book.Element("books").Attribute("cat").Value
                         ,ISBN = book.Element("books").Attribute("ISBN").Value
                         ,genre = book.Element("books").Attribute("genre").Value
                         ,Price = "?"
                         ,PublishDate="?"
                         ,Title="?"
                   };

Book Class

 public class Book
  {
    public string cat {get;set;}
    public string ISBN {get;set;}
    public string genre {get;set;}
    public string Title {get;set;}
    public string PublishDate {get;set;}
    public string Price { get; set; }
  }
A: 

This will give you what you're looking for. Of course, if there is a possibility of any of these attributes not always being present, you'd want to add some null value checks to make sure each attribute exists before calling it's Value property.

Once you have the <books> element inside your query, you can do sub queries to select the specific <Field> elements that you need.

var booksData = from book in xdoc.Descendants("books")
                select new Book
                           {
                               cat = book.Attribute("cat").Value,
                               ISBN = book.Attribute("ISBN").Value,
                               genre = book.Attribute("genre").Value,
                               Price = (from childField in book.Elements()
                                        where childField.Attribute("name").Value == "Price"
                                        select childField.Attribute("val").Value).SingleOrDefault(),
                               PublishDate = (from childField in book.Elements()
                                              where childField.Attribute("name").Value == "Publish Date"
                                              select childField.Attribute("val").Value).SingleOrDefault(),
                               Title = (from childField in book.Elements()
                                        where childField.Attribute("name").Value == "Title"
                                        select childField.Attribute("val").Value).SingleOrDefault()
                           };

One note on the code you posted in the question. The method xdoc.Descendants("root") doesn't really do anything. from book in xdoc would do the same thing. I used Descendants("books") in my answer, which is what I think you meant to do anyway.

Dennis Palmer
A: 

I agree with Dennis xdoc.Descendants("root") doesn't really do anything.

I modify code so it will check attrbiute exists or not also how you can use lambda expression.

  var booksData = from book in xdoc.Descendants("books")
                            select new Book
                            {
                                cat = book.Attribute("cat").Value,
                                ISBN = book.Attribute("ISBN").Value,
                                genre = book.Attribute("genre").Value,

                                //Dennis Code 

                               Price = (from childField in book.Elements()
                                         where childField.Attribute("name").Value == "Price"
                                         select childField.Attribute("val").Value).SingleOrDefault(),

                                //same as Dennis code but using lambda expression

                                PublishDate = book.Elements("Field").Where(p => p.Attribute("name").Value == "Publish Date")
                                              .Select(p => p.Attribute("val").Value).SingleOrDefault(),

                                 // Check if element exists or not 
                                 //if not exists it will insert empty string

                               Title = book.Elements("Field").Any( p => p.Attribute("name").Value == "Title")
                                        ? book.Elements("Field").Where(p=> p.Attribute("name").Value == "Title")
                                          .Select(p => p.Attribute("val")== null
                                                  ? string.Empty
                                                  : p.Attribute("val").Value
                                                  ).Single()
                                        : string.Empty                                };
NETQuestion
Anyone has better way for same code then please post it
NETQuestion
A: 
string xml = @"<root xmlns=''>    <books cat='F1' ISBN='01F187597' genre='Programming'>      <Field name='Title' val='XML' />       <Field name='Publish Date' val='20010424' />       <Field name='Price' val='43.00' />     </books> </root>";



            XDocument xdoc = XDocument.Parse(xml);

            var booksData = from book in xdoc.Descendants("root")
                            //I guess create this and do something with it
                            // let fieldElements = book.Descendants("Field")
                            select new Book
                            {
                                cat = book.Element("books").Attribute("cat").Value
                                   , ISBN = book.Element("books").Attribute("ISBN").Value
                                   , genre = book.Element("books").Attribute("genre").Value
                                   , Price = book.Elements("books").Elements("Field").Single(b => b.Attribute("name").Value == "Price").Attribute("val").Value
                                   , PublishDate = book.Elements("books").Elements("Field").Single(b => b.Attribute("name").Value == "Publish Date").Attribute("val").Value
                                   , Title = book.Elements("books").Elements("Field").Single(b => b.Attribute("name").Value == "Title").Attribute("val").Value
                            };

        }


        public class Book
        {
            public string cat { get; set; }
            public string ISBN { get; set; }
            public string genre { get; set; }
            public string Title { get; set; }
            public string PublishDate { get; set; }
            public string Price { get; set; }
        }

I think this is how I would do it.

Sean Barlow
your code will not work in following scenarioif attribute val is missing e.g. <Field name="Title" /> OR Title element missing <root xmlns=""><books cat="F1" ISBN="01F187597" genre="Fantasy"> <Field name="Publish Date" val="20010424" /> <Field name="Price" val="43" /> </books> </root>
NETQuestion
you bring up a good point. Thanks
Sean Barlow