LINQ to XML: отфильтруйте запрос, используя коллекцию XElement.Attributes () с XName и Value - PullRequest
3 голосов
/ 18 декабря 2009

Использование LINQ to XML, XElements и XAttributes Я бы хотел отфильтровать запрос, используя точное совпадение в коллекции XElement Attributes () IEnumerable пар XName / Value, против предоставленной коллекции IEnumerable Attributes пар XName / Value.

<container>
   <!-- logical group of settings -->
   <group name="group-one">
      <!-- setting with multiple key-value key options to return value -->
      <setting>
         <key app="a" command="go" />
         <key app="a" type="z" command="go" />
         <key app="a" type="z" flag="1" command="go" />
         <key app="a" type="z" target="OU812"/>
         <value>group-one item value A</value>
      </setting>
      <setting>
         <key app="a" />
         <key app="a" type="z" />
         <key app="a" type="z" flag="1" />
         <key app="c" type="z" command="go" />
         <value>group-one item value B</value>
      </setting>      
      ...
      ...
   </group>
   <group name="group-two">
      ...
      ...
   </group>
</container>

Я подозреваю, что использование Attributes (). SequenceEqual () с пользовательским IEqualityComparer для сравнения XAttribute.XName и XAttribute.Value - это путь, но последовательность никогда не совпадает, потому что XElement ("key"). Attributes () возвращает коллекция всех атрибутов для всех элементов в данном элементе. Я пробовал любое количество запросов linq, подобных приведенному ниже фрагменту кода, включая вложенные запросы и использование оператора «let», но, похоже, не могу сделать это правильно.

var myAttributes = new List<XAttribute> {
                                        new XAttribute("app", "a"), 
                                        new XAttribute("type", "z")
                                        };

var xGroup = doc.Elements("group").First(g=>g.Attribute("name").Value==groupName);
var xSetting = (from s in xGroup.Elements("setting")
               // AttributesComparer() compares both the XAttribute.XName and XAttribute.Value properties to determine equality
               where s.Elements("key").Attributes().SequenceEqual(myAttributes, new AttributesComparer())
               select s).FirstOrDefault();

var xValue = xSetting.Element("value");

Должен возвращать XElement, представляющий <value>group-one item value B</value>

Сейчас я остановился на использовании XPathSelectElement () - передаче строки XPath, созданной из имени / значений в предоставленной коллекции XAttributes (). В этом случае сгенерированная строка будет:

group[@name='group-one']/setting[key[@app='n' and @type='z' and count(@*)=2]]/value

Но я, как правило, не допускаю циклический просмотр коллекций для создания строк в приложении. Некоторое время я занимался этим, и, к сожалению, я озадачен тем, как реализовать более «элегантное» решение, используя компактный запрос linq (или серию запросов) с существующими методами.

Любые отзывы и / или предложения будут с благодарностью!

1 Ответ

2 голосов
/ 18 декабря 2009

Вам нужно найти параметр, в котором любой ключ соответствует, поэтому используйте метод расширения Any. Требуется только небольшое изменение:

    var xSetting = (from s in xGroup.Elements("setting")
                    // AttributesComparer() compares both the XAttribute.XName and XAttribute.Value properties to determine equality
                    where s.Elements("key").Any(key => key.Attributes().SequenceEqual(myAttributes, new AttributesComparer()))
                    select s).FirstOrDefault();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...