简体   繁体   English

字典 <string, List<ClassObj> &gt; LINQ To XML查询

[英]Dictionary<string, List<ClassObj>> LINQ To XML Query

I try to put my XML File into a Dictionary with Generic List. 我尝试将XML文件放入带有通用列表的字典中。 How I can merge correct the query List to my dictionary with correct key? 如何使用正确的键将正确的查询列表合并到字典中? Instead of .ToList() .ToDictionary is not possible? 而不是.ToList() .ToDictionary.ToDictionary吗?

<?xml version="1.0"?>
<customers>
  <cust ID="1" DeviceID="1" Name="Bob" Latitude="10" Longitude="58" Device="HW1.0"> </cust>
  <cust ID="2" DeviceID="2" Name="Jack" Latitude="28" Longitude="20" Device="HW2.2"> </cust>
</customers>

//XML attribute Name is Dict Key

public class Customers
{
    public int Longitude { get; set; }
    public int Latitude { get; set; }
    public int DeviceID { get; set; }
    public string Device { get; set; }
}

class Program
{

    private static Dictionary<string, List<Customers>> ReadXmlToDict(string filename)
    {
        // Should be Key = Xml Attribute Name Value, List of class 
        Dictionary<string, List<Customers>> dict = new Dictionary<string, List<Customers>>();

        XDocument xdoc = XDocument.Load(filename);
        var querylist = (from row in xdoc.Descendants("cust")
                         select new Customers()
                         {
                             //Name = (string)row.Attribute("Name"),  // Wrong here should be the Dic key
                             DeviceID = (int)row.Attribute("DeviceID"), // list value
                             Longitude = (int)row.Attribute("Longitude"),  // list value
                             Latitude = (int)row.Attribute("Latitude"), // list value
                             Device = (string)row.Attribute("Device")  // list value
                         }).ToList();

        return null; // null for test To.List and not Dict
    }

This is how I would implement it, I think it accomplishes what you're looking for. 这就是我要实现的方式,我认为它可以满足您的需求。 You have a class called Customers and then want to store a list of those customers with a single key...I don't follow that logic. 您有一个名为“ Customers的类,然后想用一个键存储这些客户的列表...我不遵循这种逻辑。

I created a class called Customer , which houses the information for a singular customer. 我创建了一个名为Customer的类,其中包含单个客户的信息。 Since you're returning a Dictionary<string, Customer> , where the string is the unique attribute Name in the xml, there is no use case for the value of your dictionary being a List<Customer> . 由于您要返回Dictionary<string, Customer> ,其中该字符串是xml中的唯一属性Name ,因此没有用例将您的字典值设为List<Customer> Perhaps if you have multiple customers under the same name, you would use this, but why not then make the key the (I assume) truly unique identifier, the DeviceID ? 也许如果您使用相同的名称拥有多个客户,则可以使用此名称,但是为什么不将密钥设置为(我认为)真正唯一的标识符DeviceID

namespace TestConsole
{
    class Customer
    {
        public int DeviceID;
        public int Longitude;
        public int Latitude;
        public string Device;
    }
    class Program
    {

        private static Dictionary<string, Customer> ReadXmlToDictionary(string filename)
        {
            var dict = new Dictionary<string, Customer>();

            var doc = XDocument.Load(@"C:\test.xml");

            dict = doc.Descendants("cust")
                .ToDictionary(
                    row => (string)row.Attribute("Name"),
                    row => new Customer {
                        Device = (string)row.Attribute("Device"),
                        DeviceID = (int)row.Attribute("DeviceID"),
                        Latitude = (int)row.Attribute("Latitude"),
                        Longitude = (int)row.Attribute("Longitude")
                });

            return dict;
        }

        static void Main(string[] args)
        {
            ReadXmlToDictionary(null);
        }
    }
}

结果图片

EDIT: Thought the performance related answer was interesting, so decided to try it out for this single level xml (using ID as the unique identifier). 编辑:认为与性能相关的答案很有趣,因此决定尝试针对此单级xml(使用ID作为唯一标识符)进行尝试。 Here are the results: 结果如下:

1019 Descendants took 0.0030257 seconds.
1019 Elements took 0.0028348 seconds.
10000 Descendants took 0.0098942 seconds.
10000 Elements took 0.0101478 seconds.
100000 Descendants took 0.0873025 seconds.
100000 Elements took 0.1223577 seconds.

EDIT : After creating your xsd, and generating a class from it, you would then use it as such: 编辑 :创建xsd,并从中生成一个类之后,您将可以如下使用它:

var parsed = XDocument.Parse(doc.ToString());

var serializer = new XmlSerializer(typeof(Xsds.customers));

var typedPayload = serializer.Deserialize(doc.Root.CreateReader());

var xmlAsClass = (TestConsole.Xsds.customers)typedPayload;

dict = xmlAsClass.cust
    .ToDictionary(
        row => (int)row.ID,
        row => new Customer {
            Device = row.Device,
            DeviceID = row.DeviceID,
            Latitude = row.Latitude,
            Longitude = row.Longitude,
            Name = row.Name
        });

You can do it easily by using ToDictionary() extension method. 您可以使用ToDictionary()扩展方法轻松完成此操作。 But performance wise, it is far better to use Elements() method rather than Descendants() ; 但是从性能角度来看,最好使用Elements()方法而不是Descendants() ; For further reading please read this blog post: WHY (OR WHEN) YOU SHOULD/SHOULDN'T USE DESCENDANTS() METHOD 要进一步阅读,请阅读此博客文章: 为什么(或何时)不应该/应该使用DESCENDANTS()方法

And your query will look like this: 您的查询将如下所示:

var customersDictionary = 
    xDoc.Root
        .Elements("cust")
        .ToDictionary(xe => 
                        xe.Attribute("Name").Value, xe => 
                        new Customers
                        {
                            DeviceID = (int)xe.Attribute("DeviceID"), 
                            Longitude = (int)xe.Attribute("Longitude"),  
                            Latitude = (int)xe.Attribute("Latitude"),
                            Device = (string)xe.Attribute("Device")
                        });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM