2016-08-31 2 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 = None по имени пользователя! , Я уже могу получить области внутри пользователя, и я могу их фильтровать с помощью логики 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; 

И я бы хотел чтобы получить только один Area, потому что есть только один с AccessLevel! = «Нет», но я получаю тот же результат, что и области. Я не знаю, как сообщить своей программе, что xElement.Attribute («name»). Значение, которое я хочу сравнить с «None», это значение xElement.Attribute («name»), которое я сравнивал с AccessLevel ,

Я уже пытался использовать Descendants(). Где (что-то), но я получаю то же самое. Я пытался использовать Descendants(). Где (что-то. Где-то еще), но я не могу скомпилировать.

я могу получить те области, которые я хочу с помощью:

 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» вы ожидаете иметь? Это весь элемент ''? Или просто '<Атрибут name =" Name "> FRF' element? Или что-то другое? – Ignas

+0

Я хочу получить FRF, в этом случае. Но если это будет проще, я могу получить весь объект Area, а затем я выберу это имя. В случае с пользователем это просто сработало, потому что имя является первым атрибутом, но запрос не очень хорошо сделан –

ответ

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 для пользователя, он решает мою проблему. Большое спасибо! –

Смежные вопросы