如何在c#中将XML转换为字典

时间:2014-10-22 12:42:53

标签: c# xml dictionary

我有以下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>

我希望将其中一些存储在字典Dictionary<string, List<string>>中,其中键是name元素,值是Value元素的列表。

我已经习惯了一些LINQ,但是我还没能找到字典部分。

我已经能够将一个元素放入列表中:

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

3 个答案:

答案 0 :(得分:3)

我建议:

  • 不使用XPath选择元素,而是使用Elements()方法(等)
  • 通过Dictionary<string, List<string>>使用查找而不是ToLookup。查找就像一个字典,每个键有多个值,但处理起来稍微简单(因为如果你要求丢失键,它会返回一个空序列)并且更容易构建。

所以代码看起来像是:

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

然后您可以执行以下操作:

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

所有Elements()来电的替代方法是使用Descendants(),例如。

var lookup = doc.Descendants("Client")
                .ToLookup(x => (string) x.Element("Name"),
                          x => (string) x.Element("Value"));

答案 1 :(得分:2)

我建议使用一个允许你查询的构造,我个人最喜欢查询XML是Linq to XML。

  • 首先,获取您之后的名称和价值。
  • 然后,将名称分组
  • 最后,投射到您的目标类型(字典)

示例(您可以将其直接复制并粘贴到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();

答案 2 :(得分: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);
            }


        }
    }
}