2011-03-28 30 views
1

與LINQ檢索多個XML元素由鑑於這種XML屬性

<?xml version="1.0" encoding="utf-8" ?> 
<queryableData> 
    <table displayName="Shipments" dbName="Quotes"> 
    <foreignKey column="CustomerId" references="CustomerRegistration"/> 
    <foreignKey column="QuoteStatusId" references="QuoteStatus"/> 
    <fields> 
     <field displayName="Quote Charge" dbColumn="QuoteCharge" type="Number"/> 
     <field displayName="Total Weight" dbColumn="TotalWeight" type="Number"/> 
    </fields> 
    </table> 
    <table displayName="Customers" dbName="CustomerRegistration"> 
    <fields> 
     <field displayName="First Name" dbColumn="FirstName" type="Text" /> 
     <field displayName="Last Name" dbColumn="LastName" type="Text"/> 
    </fields> 
    </table> 
</queryableData> 

我想包含顯示名稱,DbColumn和類型字段只有「行情」表中的匿名對象類型的列表。

我能夠得到兩個表的列表,下面的LINQ to XML代碼:

var xml = XElement.Load(@"C:\Sandbox\queryable.xml"); 

    // Tables 
    var tables = from el in xml.Elements("table") 
         select new 
         { 
          Text = el.Attribute("displayName").Value, 
          Value = el.Attribute("dbName").Value 
         }; 

但我不知道怎麼去的字段值,其中表元素的DBNAME屬性是「行情」。我已經得到的最接近的是一個包含值的列表清單,而不是匿名的對象與具有dbColumn /顯示名對一個項目的列表:

var columns = from el in xml.Elements("table") 
      where el.Attribute("dbName").Value.Equals("Quotes") 
      select new LookupData { 
       Text = el.Elements("fields").Elements("field").Attributes().Where(x => x.Name == "displayName").Select(x => x.Value), 
       Value = el.Elements("fields").Elements("field").Attributes().Where(x => x.Name == "dbColumn").Select(x => x.Value) 
      }; 

所以我希望這個列表中:

LookupData#1

文字: 「報價費」

值: 「QuoteCharge」

LookupData#2

文字: 「總重量」

值: 「總權重」

和我得到這個代替:

LookupData#1

文本:包含兩個字符串的列表:[0] =「報價費用」,[1] =「總重量」

值:[0] = 「QuoteCharge」,[1] = 「總權重」

回答

1

使用這樣的::

var result = xml.Elements("table"). 
    Where(el => el.Attribute("dbName").Value.Equals("Quotes")). // 1 
    SelectMany(el => el.Elements("fields").Elements("field")). // 2 
    Select(f => new 
       { 
        Text = f.Attributes().Where(x => x.Name == "displayName"). 
         Select(x => x.Value).FirstOrDefault(), 
        Value = f.Attributes().Where(x => x.Name == "dbColumn"). 
         Select(x => x.Value).FirstOrDefault() 
       } 
      ) // 3 
; 

說明:

  1. 我們選擇的元素包含兩個字符串列表其中dbName == "Quotes"
  2. 在這些元素的每個元素中,我們選擇所有field元素,並使用SelectMany來平滑結果。結果將是一個IEnumerable<XElement>
  3. 對於每一個領域,我們選擇一個匿名類型與Text屬性設置爲名爲「顯示名」第一屬性的值和Value屬性設置爲一個名爲「dbColumn」

的第一屬性的值您的方法問題基本上是,您將第2步放入匿名類型的創建中。或換句話說:您爲「Quotes」元素創建了一個匿名類型實例,而不是每個「field」元素。