2016-08-31 176 views
2

我有以下XML文件:的Xml LINQ查詢(獲取元素的屬性和屬性值)

<Object type="User"> 
    <Attribute name="Name">usernameExample</Attribute> 
    <Attribute name="Title">FHen</Attribute> 
    <Attribute name="AdministratedBy">Admin</Attribute> 
    <Attribute name="Password">123</Attribute> 
    <Attribute name="TimeOut">00:20:00</Attribute> 
    <Object type="AreasFolder"> 
     <Attribute name="Name">Areas</Attribute> 
     <Attribute name="Comment">This folder contains ...</Attribute> 
     <Object type="Area"> 
      <Attribute name="Name">RootArea</Attribute> 
      <Attribute name="AccessLevel">None</Attribute> 
     </Object> 
     <Object type="Area"> 
      <Attribute name="Name">FRF</Attribute> 
      <Attribute name="AccessLevel">Admin</Attribute> 
     </Object> 
    </Object> 
</Object> 

,我的目標是獲得具有ACCESSLEVEL用戶名=無區域的名字! 。我已經可以得到用戶內的區域,我可以使用c#邏輯來過濾它們,但我想用Linq Xml查詢來做到這一點。

現在我已經做了以下內容:

在我的主:

logic.tryXdoc("usernameExample"); 

在我Logic.cs:

public void tryXdoc(string username) 
    { 
     List<string> lista = new List<string>(); 

     XElement ConfigData = XElement.Load(UsersXmlPath); 

     XElement scadaUsers = 
      (from xElement in ConfigData.Elements("Object") 
       //where (string)xElement.Element("type") == "User" 
      select xElement).First(); 

     XElement usersFolder = 
      (from xElement in scadaUsers.Elements("Object") 
      where (string)xElement.Attribute("type") == "UsersFolder" 
      select xElement).First(); 

     IEnumerable<XElement> users = 
      from xElement in usersFolder.Elements("Object") 
      where (string)xElement.Attribute("type") == "User" 
      select xElement; 

     XElement user = 
      (from xElement in users 
       where (string)xElement.Element("Attribute").Attribute("name") == "Name" 
       && (string)xElement.Element("Attribute") == username 
       select xElement).First(); 

     XElement areasFolder = 
      (from xElement in user.Elements("Object") 
       where (string)xElement.Attribute("type") == "AreasFolder" 
       select xElement).First(); 

     IEnumerable<XElement> areas = 
      from xElement in areasFolder.Elements("Object") 
      where (string)xElement.Attribute("type") == "Area" 
      select xElement;   
    } 

現在,我想是這樣的:

 IEnumerable<XElement> visibleAreas = 
      from xElement in areas.Elements("Attribute") 
      where 
      (string)xElement.Attribute("name") == "AccessLevel" 
      && (string)xElement.Attribute("name").Value != "None" 
      select xElement; 

我想得到只有一個區域,因爲只有一個AccessLevel!=「無」,但我得到了與區域相同的結果。我不知道如何告訴我的程序xElement.Attribute(「name」)。我希望它與「None」比較的值,它是與AccessLevel比較的xElement.Attribute(「name」)的值。

我已經嘗試使用Descendants()。哪裏(某事)但我得到相同的。我嘗試使用Descendants()。Where(something.Where(something))但我無法編譯。

我能得到我想要使用領域:

 List<List<XElement>> listAreaAttributes = new List<List<XElement>>(); 

     foreach (XElement xElement in areas) 
     { 
      List<XElement> areaAttributes = new List<XElement>(); 

      foreach (XElement xEl in xElement.Elements("Attribute")) 
      { 
       areaAttributes.Add(xEl); 
      } 

      listAreaAttributes.Add(areaAttributes); 
     } 

,然後比較areaAttributes但我知道這是可能的查詢,使這個,所以我不希望使用processment使這個。

+0

絕對有可能爲此編寫一個LINQ查詢。你能否澄清一下你所期望的「visibleAreas」的價值?它是整個''元素嗎?或者只是一個' FRF'元素?或者是其他東西? – Ignas

+0

在這種情況下,我想獲得FRF。但如果它更容易,我可以得到整個區域對象,然後我從那裏取出名稱。 在用戶的情況下,它只是工作,因爲名稱是第一個屬性,但查詢不是很好完成 –

回答

1

如何修改這個以適合你的用戶,如果你想在每個用戶的基礎上做到這一點。這假定XML的順序是準確的,並且AccessLevel名稱始終是緊鄰AccessLevel的節點。

List<string> visibleAreas = ConfigData.Descendants("Attribute") 
    .Where(x => x.Attribute("name").Value == "AccessLevel") 
    .Where(x => x.Value != "None") 
    .Select(x => ((XElement)x.PreviousNode).Value) 
    .ToList(); 
+0

我得到213查詢結果,因爲我的xml文件很大,並且有很多用戶有很多區域。我只是把我的問題的一部分的XML。但是如果我替換用戶的ConfigData,它解決了我的問題。非常感謝你! –