views:

492

answers:

2

I have an XML which looks something like this

<?xml version="1.0" encoding="utf-8" ?>
<Applicant>
  <NameValueGroup attribute="Name">
    <NameValue desc="One" value="test1"/>
    <NameValue desc="Two" value="test2"/>
    <NameValue desc="Three" value="test3"/>
    <NameValue desc="Four" value="test4"/>
  </NameValueGroup>
  <NameValueGroup attribute="News">
    <NameValue desc="news1" value="Something1"/>
    <NameValue desc="news2" value="Something2"/>
    <NameValue desc="news3" value="Something3"/>
    <NameValue desc="news4" value="Something4"/>
  </NameValueGroup>
</Applicant>

How will I write a LINQ to XML query to deserialize this XML.

A: 

This works but it has no error handling for empty/missing values. Enjoy.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

namespace LinqToXmlExample
{
    class Program
    {
        static void Main(string[] args)
        {
            var x = XDocument.Load("input.xml");

            var content =
                from node in x.Descendants("Applicant").Descendants("NameValueGroup")
                select new NameValueGroup()
                           {
                                Attribute = node.Attribute("attribute").Value,
                                NameValues = GetNameValues(node.Descendants())
                           };

            foreach (NameValueGroup item in content)
            {
                Console.WriteLine(item.Attribute);
                foreach (var name in item.NameValues)
                {
                    Console.WriteLine("{0} - {1}", name.Desc, name.Value);
                }
            }

            Console.ReadLine();
        }

        static List<NameValue> GetNameValues(IEnumerable<XElement> elements)
        {
            var x = new List<NameValue>();
            if(elements != null && elements.Any())
            {
                x =
                    (from node in elements
                    select new NameValue()
                               {
                                   Desc = node.Attribute("desc").Value,
                                   Value = node.Attribute("value").Value
                               }).ToList();
            }
            return x;
        }

        class NameValueGroup
        {
            public string Attribute { get; set; }
            public List<NameValue> NameValues { get; set; }
        }

        class NameValue
        {
            public string Desc { get; set; }
            public string Value { get; set; }
        }
    }
}
Nathan Taylor
A tip about handling missing values: rather than using XAttribute.Value, use the explicit conversion operators it has. They check for absent attribute (i.e. null XAttribute) automatically where it makes sense, so you don't have to. I.e. instead of ...`.Attribute("foo").Value`, write `(string)`...`.Attribute("foo")` - and then check value for `null` to see if attribute was missing. Note also that it has overloads for both nullable and non-nullable versions for types such as `int`
Pavel Minaev
A: 

I created a class called Applicant, with a property of type Dictionary with key string and value another Dictonary<string, string>

public class Applicant {
    public Dictionary<string, Dictionary<string, string>> NameValueGroup { get; set; }
}

To fill this property I do this.

XDocument document = XDocument.Load("data.xml");
Applicant applicant = new Applicant();

applicant.NameValueGroup = document.Element("Applicant").
                            Descendants("NameValueGroup").
                            ToDictionary(keyElement => keyElement.Attribute("attribute").Value, valueElement => valueElement.Descendants().
                                 ToDictionary(e => e.Attribute("desc").Value, e => e.Attribute("value").Value));

Please excuse the bad formating. It's hard to make that query nice to look at!

Manticore