0

I have the following XML:

<Axis>
    <Collections>
        <Collection>
            <Client>
                <Name>Client 1</Name> 
                <Value>345</Value> 
            </Client>
        </Collection>
        <Collection>
            <Client>
                <Name>Client 1</Name> 
                <Value>4532</Value> 
            </Client>
        </Collection>
        <Collection>
            <Client>
                <Name>Client 1</Name> 
                <Value>235</Value> 
            </Client>
        </Collection>
        <Collection>
            <Client>
                <Name>Client 1</Name> 
                <Value>8756</Value> 
            </Client>
        </Collection>
        <Collection>
            <Client>
                <Name>Client 1</Name> 
                <Value>76</Value> 
            </Client>
        </Collection>
    </Collections>
    <Collections>
        <Collection>
            <Client>
                <Name>Client 2</Name> 
                <Value>56</Value> 
            </Client>
        </Collection>
        <Collection>
            <Client>
                <Name>Client 2</Name> 
                <Value>43</Value> 
            </Client>
        </Collection>
        <Collection>
            <Client>
                <Name>Client 2</Name> 
                <Value>34</Value> 
            </Client>
        </Collection>
        <Collection>
            <Client>
                <Name>Client 3</Name> 
                <Value>42</Value> 
            </Client>
        </Collection>
        <Collection>
            <Client>
                <Name>Client 3</Name> 
                <Value>23</Value> 
            </Client>
        </Collection>
    </Collections>
</Axis>

and I would like to store some of this in a dictionary Dictionary<string, List<string>> where the key is the name element and the value is a list of the Value elements.

I have mucked around with a bit of LINQ, but I have not been able to work out the dictionary part.

I have been able to get one element into a list:

myDoc.XPathSelectElements("//Axis/Collections/Collection/Client/Value")
     .Select(v => v.Value)
     .ToList();

3 Answers 3

3

I would suggest:

  • Not using XPath to select elements, but using the Elements() method (etc) instead
  • Using a lookup instead of a Dictionary<string, List<string>>, via ToLookup. A lookup is like a dictionary with multiple values per key, but slightly simpler to handle (as it returns an empty sequence if you ask for a missing key) and much easier to construct.

So the code would look something like:

var lookup = doc.Root
                .Elements("Collections")
                .Elements("Collection")
                .Elements("Client")
                .ToLookup(x => (string) x.Element("Name"),
                          x => (string) x.Element("Value"));

You can then do things like:

foreach (var value in lookup["Client 1"])
{
    ...
}

An alternative to all the Elements() calls would be to use Descendants(), e.g.

var lookup = doc.Descendants("Client")
                .ToLookup(x => (string) x.Element("Name"),
                          x => (string) x.Element("Value"));
Sign up to request clarification or add additional context in comments.

Comments

2

I would suggest using a construct that allows you to query, my personal favourite for querying XML is Linq to XML.

  • First, get what you're after (the name and value).
  • Then, group that on the name
  • Finally, project to your target type (a dictionary)

Example (you can copy and paste this straight into LinqPad):

var xml = @"<Axis>
<Collections>
   <Collection>
       <Client>
           <Name>Client 1</Name> 
           <Value>345</Value> 
       </Client>
   </Collection>
   <Collection>
       <Client>
           <Name>Client 1</Name> 
           <Value>4532</Value> 
       </Client>
   </Collection>
   <Collection>
       <Client>
           <Name>Client 1</Name> 
           <Value>235</Value> 
       </Client>
   </Collection>
   <Collection>
       <Client>
           <Name>Client 1</Name> 
           <Value>8756</Value> 
       </Client>
   </Collection>
   <Collection>
       <Client>
           <Name>Client 1</Name> 
           <Value>76</Value> 
       </Client>
   </Collection>
</Collections>
<Collections>
   <Collection>
       <Client>
           <Name>Client 2</Name> 
           <Value>56</Value> 
       </Client>
   </Collection>
   <Collection>
       <Client>
           <Name>Client 2</Name> 
           <Value>43</Value> 
       </Client>
   </Collection>
   <Collection>
       <Client>
           <Name>Client 2</Name> 
           <Value>34</Value> 
       </Client>
   </Collection>
   <Collection>
       <Client>
           <Name>Client 3</Name> 
           <Value>42</Value> 
       </Client>
   </Collection>
   <Collection>
       <Client>
           <Name>Client 3</Name> 
           <Value>23</Value> 
       </Client>
   </Collection>
</Collections>
</Axis>";

var doc = XDocument.Parse(xml);
var dict = (from row in doc.Root.Descendants("Client")
            let name = row.Element("Name").Value
            let value = row.Element("Value").Value
            group value by name into grp
            select new { grp.Key, Values = grp.ToList() }).ToDictionary(d => d.Key, d => d.Values);
dict.Dump();

Comments

0
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace XMLToDictionary
{
    class Program
    {
        static void Main(string[] args)
        {
            var doc = XDocument.Load("c:\\Test.xml");

            var clients = doc.Descendants().Where(e => e.Name.LocalName == "Client").ToList();
            Dictionary<string, List<string>> dic = new Dictionary<string, List<string>>();
            foreach (var client in clients)
            {
                string key = client.Elements().First(e => e.Name.LocalName == "Name").Value;
                string val = client.Elements().First(e => e.Name.LocalName == "Value").Value;
                if (!dic.ContainsKey(key))
                {
                    dic[key] = new List<string>();
                }
                dic[key].Add(val);
            }


        }
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.