使用 LINQ 指定祖先节点从节点获取所有属性值
Getting all attribute values from node by specifying the ancestor node using LINQ
假设我有以下 xml 文件:
<ModuleSets>
<ServiceModuleSet Name="serverModules">
<Modules>
<ServiceModule Name="ServerModule1"/>
<ServiceModule Name="ServerModule2"/>
</Modules>
</ServiceModuleSet>
<ServiceModuleSet Name="testBenchModules">
<Modules>
<ServiceModule Name="testBenchModule1"/>
<ServiceModule Name="testBenchModule2"/>
</Modules>
</ServiceModuleSet>
<ServiceModuleSet Name="hostComputerModules">
<Modules>
</Modules>
</ServiceModuleSet>
</ModuleSets>
我想从 ServiceModule
节点获取所有属性,方法是在 ServiceModuleSet
节点中搜索,其中属性名称等于 "serverModules"
.
我是 LINQ 的新手,尝试了以下代码:
IEnumerable<string> allServerModules = from item in xmlDocument.Descendants("ServiceModuleSet")
where item.Descendants("ServiceModuleSet").Any(attribute => attribute.Value == "serverModules")
select (string)item.Attribute("Name");
foreach (var serverModule in allServerModules)
{
Console.WriteLine(serverModule);
}
很遗憾,我没有将任何结果打印到控制台。使用 LINQ 解决它的正确方法是什么?
我喜欢用字典:
XDocument doc = XDocument.Load(FILENAME);
Dictionary<string, List<string>> dict = doc.Descendants("ServiceModuleSet")
.GroupBy(x => (string)x.Attribute("Name"), y => y)
.ToDictionary(x => x.Key, y => y.Descendants("ServiceModule").Select(z => (string)z.Attribute("Name")).ToList());
这是我的解决方案:
var parsedXml = XDocument.Load("sample.xml");
var serverModules = parsedXml.Descendants("ServiceModuleSet")
.FirstOrDefault(set => set.Attribute("Name")?.Value == "serverModules");
var moduleNames = serverModules?.Descendants("ServiceModule")
.Select(module => module.Attribute("Name")?.Value)
.Where(value => !string.IsNullOrEmpty(value));
if (moduleNames == null) return;
foreach (var moduleName in moduleNames)
{
Console.WriteLine(moduleName);
}
- 首先,我尝试检索
ServiceModuleSet
,它的 Name
属性等于 "serverModules"
1.1 如果没有任何后代(满足过滤条件)那么我们不想失败并出现异常,这就是为什么我使用 FirstOrDefault
而不是 First
1.2 相同的容错逻辑也应用于 Name
属性,这就是我使用空条件运算符 (Attribute("Name")?.
) 的原因
- 如果我找到了想要的节点,那么我可以寻找它的子节点来询问它们的
Name
属性
2.1 再次使用空条件运算符 (serverModules?.Descendants
) 使我们的代码更健壮
2.2 ServiceModule
节点可能有也可能没有 Name
属性,这就是为什么我使用空条件运算符 (.Attribute("Name")?.
) 和空字符串过滤 (!string.IsNullOrEmpty
) 的组合。
- 如果我成功并检索到了一些数据,那么我会打印它们,否则我会提前退出
假设我有以下 xml 文件:
<ModuleSets>
<ServiceModuleSet Name="serverModules">
<Modules>
<ServiceModule Name="ServerModule1"/>
<ServiceModule Name="ServerModule2"/>
</Modules>
</ServiceModuleSet>
<ServiceModuleSet Name="testBenchModules">
<Modules>
<ServiceModule Name="testBenchModule1"/>
<ServiceModule Name="testBenchModule2"/>
</Modules>
</ServiceModuleSet>
<ServiceModuleSet Name="hostComputerModules">
<Modules>
</Modules>
</ServiceModuleSet>
</ModuleSets>
我想从 ServiceModule
节点获取所有属性,方法是在 ServiceModuleSet
节点中搜索,其中属性名称等于 "serverModules"
.
我是 LINQ 的新手,尝试了以下代码:
IEnumerable<string> allServerModules = from item in xmlDocument.Descendants("ServiceModuleSet")
where item.Descendants("ServiceModuleSet").Any(attribute => attribute.Value == "serverModules")
select (string)item.Attribute("Name");
foreach (var serverModule in allServerModules)
{
Console.WriteLine(serverModule);
}
很遗憾,我没有将任何结果打印到控制台。使用 LINQ 解决它的正确方法是什么?
我喜欢用字典:
XDocument doc = XDocument.Load(FILENAME);
Dictionary<string, List<string>> dict = doc.Descendants("ServiceModuleSet")
.GroupBy(x => (string)x.Attribute("Name"), y => y)
.ToDictionary(x => x.Key, y => y.Descendants("ServiceModule").Select(z => (string)z.Attribute("Name")).ToList());
这是我的解决方案:
var parsedXml = XDocument.Load("sample.xml");
var serverModules = parsedXml.Descendants("ServiceModuleSet")
.FirstOrDefault(set => set.Attribute("Name")?.Value == "serverModules");
var moduleNames = serverModules?.Descendants("ServiceModule")
.Select(module => module.Attribute("Name")?.Value)
.Where(value => !string.IsNullOrEmpty(value));
if (moduleNames == null) return;
foreach (var moduleName in moduleNames)
{
Console.WriteLine(moduleName);
}
- 首先,我尝试检索
ServiceModuleSet
,它的Name
属性等于"serverModules"
1.1 如果没有任何后代(满足过滤条件)那么我们不想失败并出现异常,这就是为什么我使用FirstOrDefault
而不是First
1.2 相同的容错逻辑也应用于Name
属性,这就是我使用空条件运算符 (Attribute("Name")?.
) 的原因
- 如果我找到了想要的节点,那么我可以寻找它的子节点来询问它们的
Name
属性
2.1 再次使用空条件运算符 (serverModules?.Descendants
) 使我们的代码更健壮
2.2ServiceModule
节点可能有也可能没有Name
属性,这就是为什么我使用空条件运算符 (.Attribute("Name")?.
) 和空字符串过滤 (!string.IsNullOrEmpty
) 的组合。 - 如果我成功并检索到了一些数据,那么我会打印它们,否则我会提前退出