2016-03-03 87 views
0

我嘗試將我的XML文件放入具有通用列表的字典中。我如何使用正確的鍵將正確的查詢列表合併到我的字典中?而不是.ToList().ToDictionary是不可能的?字典<字符串,列表<ClassObj>> LINQ到XML查詢

<?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 
    } 
+0

也許是這樣的'(從xdoc.Descendants行(「卡斯特」))ToDictionary( k =>(string)row.Attribute(「ID」),(v => select new Customers(){})。ToList());'? – Tim

+0

謝謝,但我仍然有問題,使linq查詢正確的字典,名單>。語法仍然是錯誤的,但你的幫助給了我一個想法。我會嘗試。 – Shazter

回答

2

這是我將如何實現它,我覺得它實現你在找什麼。你有一個名爲Customers的課程,然後希望用一個鍵存儲這些用戶的列表......我不遵循這個邏輯。

我創建了一個名爲Customer的類,其中包含單個客戶的信息。由於您要返回Dictionary<string, Customer>,其中字符串是xml中的唯一屬性Name,因此您的字典的值爲List<Customer>沒有用例。也許如果你有多個同名的客戶,你可以使用這個,但爲什麼不把這個密鑰(我認爲)真正的唯一標識符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); 
     } 
    } 
} 

Image of results

編輯:原以爲與性能相關的回答很有趣,於是決定(使用ID作爲唯一標識符)嘗試一下這種單級XML。下面是結果:

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. 

編輯: 創建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 
     }); 
+0

你是完全正確的,我不需要名單,因爲每個客戶應該是唯一的名稱。我不僅誤解了正確的語法。非常感謝! – Shazter

+0

與我的主題相關我還有一個問題。我真的不喜歡硬編碼值,例如該類爲客戶。重用非常低,基於Attributes的類將會很不錯,包括通用的xml屬性名稱。 – Shazter

+0

您可以並且應該創建一個xsd。如果您不想手動創建xsd,可以使用它:http://www.freeformatter.com/xsd-generator.html#ad-output。由於其中一些是可以空的,我不認爲你可以在這裏使用'xsd.exe':http://stackoverflow.com/questions/32610770/deserialization-of-nullable-value-with -xsd-exe-generated-class,所以使用xsd2code或wscfblue或其他工具來生成類。 –

1

您可以輕鬆地做到這一點使用ToDictionary()擴展方法。但性能方面,使用Elements()方法而不是Descendants()要好得多;進一步的閱讀,請閱讀這篇博客: WHY (OR WHEN) YOU SHOULD/SHOULDN’T USE DESCENDANTS() METHOD

,且查詢看起來是這樣的:

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") 
         }); 
+1

該鏈接非常有幫助。 – Shazter

+0

@Shazter,請考慮將最有用的答案標記爲可接受的答案,以便對其他人有用。 –

相關問題