#c# #linq
#c# #linq
Вопрос:
У меня есть следующий XML-файл:
<?xml version="1.0" encoding="utf-8"?>
<nodes>
<node id="1">
<subnode name="a" value="1" />
<subnode name="b" value="2" />
</node>
<node id="2">
<subnode name="a" value="2" />
<subnode name="b" value="2" />
</node>
<node id="3">
<subnode name="a" value="1" />
<subnode name="b" value="1" />
</node>
<node id="4">
<subnode name="a" value="1" />
<subnode name="b" value="2" />
</node>
</nodes>
Мне нужно выбрать идентификаторы узлов, которые имеют оба a=1
и b=2
(в данном случае узел 1 и узел 4).
Я бы предпочел сделать это с помощью linq, и у меня есть следующий код для выбора тех, которые есть a=1
. Как мне расширить код, чтобы также выполнить второе требование?
var document = XDocument.Load(@"c:tempsubnodes.xml");
var x = from topnode in document.Descendants("nodes")
let nodes = topnode.Descendants("node") from n in nodes
let subnodes = n.Descendants("subnode") from s in subnodes
where s.Attribute("name").Value == "a" amp;amp; s.Attribute("value").Value == "1"
select n.Attribute("id").Value;
РЕДАКТИРОВАТЬ: я создал скрипку .NET здесь: https://dotnetfiddle.net/mOg3wv
Комментарии:
1.
where (s.Attribute("name").Value == "a" amp;amp; s.Attribute("value").Value == "1") amp;amp; (s.Attribute("name").Value == "b" amp;amp; s.Attribute("value").Value == "2")
2. @Aarif: атрибут «name» не может быть одновременно
a
иb
. При этом узлы не выбираются.3.
or
в этом случае используйте условие||
4. @Aarif: это также выбирает узел 2 и 3.
5. понял, позвольте мне обновить запрос
Ответ №1:
Вы можете использовать следующее.
var result = document.Descendants("node").Where(x=>x.Descendants("subnode")
.All(c=>(c.Attribute("name").Value == "a" amp;amp; c.Attribute("value").Value=="1") ||
(c.Attribute("name").Value == "b" amp;amp; c.Attribute("value").Value=="2")))
.Select(x=>x.Attribute("id").Value);
Вывод
1
4
Ответ №2:
ОБНОВЛЕНИЕ 2:
вот решение на основе LINQ для этого
var nodes = document.Descendants("nodes").Descendants("node");
return (from node in nodes
let aSubNode = node.Descendants("subnode")
.FirstOrDefault(a => a.Attribute("name")?.Value == "a" amp;amp; a.Attribute("value")?.Value == "1")
let bSubNode = node.Descendants("subnode")
.FirstOrDefault(a => a.Attribute("name")?.Value == "b" amp;amp; a.Attribute("value")?.Value == "2")
where aSubNode != null amp;amp; bSubNode != null
select node.Attribute("id")?.Value).ToList();
ОБНОВЛЕНИЕ 1:
Я обновил код, чтобы считывать id
значение атрибута из node
элемента вместо subnode
.
ОРИГИНАЛ:
ниже приведен не весь LINQ, но это должно решить вашу проблему
var nodes = document.Descendants("nodes").Descendants("node");
var ids=new List<string>();
foreach (var node in nodes)
{
var aSubNode = node.Descendants("subnode")
.FirstOrDefault(a => a.Attribute("name")?.Value == "a" amp;amp; a.Attribute("value")?.Value == "1");
var bSubNode=node.Descendants("subnode")
.FirstOrDefault(a => a.Attribute("name")?.Value == "b" amp;amp; a.Attribute("value")?.Value == "2");
if (aSubNode==null || bSubNode==null)
continue;
ids.Add(node.Attribute("id")?.Value);
}
Комментарии:
1. Боюсь, это возвращает мне список из 4 нулевых строк. Но спасибо за ваши усилия.
2. позвольте мне проверить это
3. @PalleDue вы можете попробовать сейчас?, Я обновил ответ.
4. Да, это дает мне ожидаемый ответ. Однако я немного неохотно принимаю это как ответ. Это не совсем элегантный запрос linq, который я искал. Я подожду и посмотрю, появится ли лучшее решение.
5. конечно, @PalleDue, я попытался сначала использовать все
LINQ
, я попробую, смогу ли я преобразовать это вLINQ