我是Linq和XDocument的新手,我无法在任何地方找到解决方案的类似问题,所以这里有:
这是我要解析的XML:
<environment>
<objectBuilder>
<service id="1">
<!--Service:"MagicService">
</service>
<service id="2">
<!--Service:"RubbishService">
</service>
<service id="3">
<!--Service:"MediocreService">
</service>
</objectBuilder>
</environment>
我希望最终使用一个类似于以下内容的列表:
("1 MagicService","2 RubbishService","3 MediocreService")
我已经尝试将注释和ID读入两个不同的列表,然后将它们组合在一起,但这不是一个足够好的解决方案,因为在我的现实世界中,可能存在没有注释名称的服务。
我目前的解决方案如下:
List<string> comments = doc.Elements("Environment")
.Elements("objectBuilder")
.Elements("service")
.Nodes()
.OfType<XComment>()
.Select(c => c.Value)
.Where(c=> c.StartsWith("Service"))
.ToList());
List<string> serviceGuides = doc.Elements("Environment")
.Elements("objectBuilder")
.Elements("service")
.Attributes(XName.Get("id"))
.Select(c => c.Value)
.ToList());
然后,如果列表大小相同,那么我会通过for循环并逐字地连接它们。必须有一个更优雅的解决方案吗?
感谢您的帮助,对不起,如果这是一个重复/愚蠢的问题
答案 0 :(得分:0)
这是一种可能的方式:
var result = (from service in doc.Elements("environment")
.Elements("objectBuilder")
.Elements("service")
//get service id attribute
select (string)service.Attribute("id")
+ " " +
//get the first comment node which value starts with "Service"
//and then extract the value between first quotes pair
service.Nodes()
.OfType<XComment>()
.Select(c => c.Value)
.FirstOrDefault(c => c.StartsWith("Service"))
.Split('"')[1]
).ToList();
foreach (var r in result)
{
Console.WriteLine(r);
}
<强> dotnetfiddle demo
强>
输出
1 MagicService
2 RubbishService
3 MediocreService
答案 1 :(得分:0)
这应该有用。
var serviceElements = xDoc.Elements("environment")
.Elements("objectBuilder")
.Elements("service")
.ToList();
var result = (from element in serviceElements
let attribute = element.Attribute("id").Value
let name = element
.Nodes()
.OfType<XComment>()
.Select(c => c.Value)
.FirstOrDefault(c => c.StartsWith("Service"))
.Split('"')[1]
select string.Format("{0} {1}", attribute, name)).ToList();
Resharper非常适合这样的事情。您可以编写循环,resharper将帮助您将其转换为linq。您可以轻松组合上面的两个表达式。您可能还想添加空引用检查。