2015-09-22 69 views
0

我有一個簡單的XML文檔在我的應用程序的設置,如下所示:查詢XML屬性使用LINQ

<Settings> 
    <Server> 
     <Id>1</Id> 
     <Name>SRV123456</Name> 
     <Par Type="Desktop" Region="Western">12</Par> 
     <Par Type="Laptop" Region="Western">15</Par> 
     <Par Type="Desktop" Region="Eastern">22</Par> 
     <Par Type="Laptop" Region="Eastern">25</Par> 
     <State>WA</State> 
    </Server> 
</Settings> 

,我試圖用C#和LINQ查詢它,使用此代碼:

xelement = XElement.Load(startpath + "\\Settings.xml"); 
var sn = from sl in xelement.Elements("Server") 
     where (string)sl.Element("State") == "WA" 
     where (string)sl.Element("Par").Attribute("Region") == "Western" 
     where (string)sl.Element("Par").Attribute("Type") == "Desktop" 
     select sl; 

     foreach (XElement xele in sn) 
     { 
       Console.WriteLine(xele); 
       Console.WriteLine(xele.Element("Par").Value); 
     } 

這適用於第一個「Par」值,並將返回「12」。但是,如果我改變

where (string)sl.Element("Par").Attribute("Type") == "Desktop" 

where (string)sl.Element("Par").Attribute("Type") == "Laptop" 

它不返回任何結果...我缺少什麼?

+0

它試圖混合兩種查詢風格真的很醜。堅持任一(最好 - 代碼版本) –

+1

'元素'返回文檔順序中的第一個元素。該元素上的屬性將是被檢查的屬性。 – Tim

+0

沒有理由一個人會工作,另一個不會。仔細檢查你的拼寫和大寫/小寫字母。 – jdweng

回答

1

下面是工作,看起來更漂亮查詢:

var parValue = xdoc.Descendants("Par") 
    .Where(par=>par.Parent.Element("State")?.Value == "WA") 
    .Where(par=>par.Attribute("Region")?.Value == "Western") 
    .Where(par=>par.Attribute("Type")?.Value == "Laptop") 
    .Select(par=>par.Value) 
    .FirstOrDefault(); 

注意的?是一個CS6功能,如果使用CS5,只需省略?,如果需要則檢查爲空

+2

你也可以在早期版本的C#中執行'.Where(par =>(string)par.Attribute(「Region」)==「Western」)''。如果未找到該屬性,則顯式轉換爲'string'將安全地返回null。 – Tim

+0

工作完美 - 我剛剛刪除了'?',並且每次都返回結果。我希望我今天早上發佈了這個問題......謝謝! – BigfootNick

+0

@BigfootNick絕對做每個Tim的評論,以避免NRE –

0

我絕不意味着LINQ

專家然而

var sn = from sl in xelement.Elements("Server") 
      where (string)sl.Element("State") == "WA" 
      where (string)sl.Element("Par").Attribute("Region") == "Western" 
      where (string)sl.Element("Par").Attribute("Type") == "Desktop" 
      select sl; 

我相信僅僅意味着返回元素,其中屬性(「類型」)==「桌面」 意味着只返回那些地方等於「桌面」 ......所以,當你循環有沒有在你的結果集

變化

var sn = from sl in xelement.Elements("Server") 
      where (string)sl.Element("State") == "WA" 
      where (string)sl.Element("Par").Attribute("Region") == "Western" 
       select sl; 

它應該返回所有的類型......不只是「桌面」

0

也許您試圖返回Western/Laptop值= 15?

var state = "WA"; 
var region = "Western"; 
var type = "Laptop"; 
var xElement = XElement.Parse(@"<Settings> 
    <Server> 
     <Id>1</Id> 
     <Name>SRV123456</Name> 
     <Par Type='Desktop' Region='Western'>12</Par> 
     <Par Type='Laptop' Region='Western'>15</Par> 
     <Par Type='Desktop' Region='Eastern'>22</Par> 
     <Par Type='Laptop' Region='Eastern'>25</Par> 
     <State>WA</State> 
    </Server> 
</Settings>"); 

foreach (XElement server in xElement.XPathSelectElements(
      String.Format("//Server[State='{0}']", state))) 
{ 
    Console.WriteLine(server); 

    // In your sample the Western/Desktop is the first element 
    // If you want a specific Par element, you should query again with that filter 
    foreach (XElement par in server.XPathSelectElements(
       String.Format("Par[@Region='{0}' and @Type='{1}']", region, type))) 
     Console.WriteLine(par.Value); ; 
} 

我選擇XPath而不是Linq來過濾XML文檔,因爲XPath對我來說似乎更簡潔。