我有一个HashSet,包含我要检索的xml子节点。我使用以下linq(不工作)尝试获取所有孩子并返回父母:
的xml:
<team>
<bob>a</bob>
<mary>b</mary>
<joe>c</joe>
</team>
<team>
<john>d</john>
</team>
HashSet的:
HashSet<string> people = new HashSet<string> { "mary", "joe", "john" };
LINQ:
IEnumerable<XElement> result = from d in doc.Descendants("team")
where people.Contains(d.Descendants().Name.LocalName)
select d;
应该回归:
<team>
<mary>b</mary>
<joe>c</joe>
</team>
<team>
<john>d</john>
</team>
但它不起作用。任何帮助,将不胜感激。感谢。
更新#1
我正在添加一个完整的示例,它不返回任何内容:
public void test1()
{
var xml =
@"<?xml version=""1.0"" encoding=""utf-8""?>
<hereistheroot>
<team>
<bob>a</bob>
<mary>b</mary>
<joe>c</joe>
</team>
<team>
<john>d</john>
</team>
</hereistheroot>";
XElement doc = XElement.Parse(xml);
HashSet<string> people = new HashSet<string> { "mary", "joe", "john" };
IEnumerable<XElement> result = from d in doc.Descendants("team")
where people.Contains(d.Name.LocalName)
select d;
}
它什么都不返回。它应该返回两个XElement对象:
第一个:
<team>
<mary>b</mary>
<joe>c</joe>
</team>
第二个:
<team>
<john>d</john>
</team>
注意:为了测试,删除linq中的“Where”子句,它将正确返回两个XElement对象,但这是主要问题:我需要获取“Where”子句允许我根据HashSet选择人员。感谢。
答案 0 :(得分:1)
在我看来,你实际上是想在这里完成两件不同的事情:
team
元素。team
元素的新XML DOM,并且在这些元素中只有那些具有您的集合中名称的子节点。如果这是正确的,那么以下内容将实现:
IEnumerable<XElement> result = from d in doc.Descendants("team")
let validDescendants = d.Descendants()
.Where(c => people.Contains(c.Name.LocalName)).ToArray()
where validDescendants.Length > 0
select new XElement(d.Name, validDescendants);
使用更多查询表达式语法(即初始化validDescendants
)的上述替代方法:
IEnumerable<XElement> result = from d in doc.Descendants("team")
let validDescendants =
(from c in d.Descendants()
where people.Contains(c.Name.LocalName)
select c).ToArray()
where validDescendants.Length > 0
select new XElement(d.Name, validDescendants);
请注意,此方法保持原始doc
树不变,而是返回具有所需配置的全新team
元素的枚举。
如果您只是保留doc
树并从已返回的team
元素中删除子元素,则可以执行以下操作:
IEnumerable<XElement> result = from d in doc.Descendants("team")
where d.Descendants()
.Any(c => people.Contains(c.Name.LocalName))
select d;
foreach (XElement element in result)
{
foreach (XElement child in element.Descendants().ToList())
{
if (!people.Contains(child.Name.LocalName))
{
child.Remove();
}
}
}
当然,在该示例中,它将保留未包含至少一个在您的集合中具有名称的元素的任何team
元素。当然,这也是可以修复的,但是因为你似乎只想要在过滤后检索非空的元素,所以我假设上面的第一个例子更符合你想要的。我将第二个仅作为变体展示,如果你有更具体的东西,你没有在你的问题中完全描述,那么你可以继续使用。