如何使用XDocument和Linq读入与子注释

时间:2016-01-29 13:56:42

标签: c# xml linq parsing xml-parsing

我是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循环并逐字地连接它们。必须有一个更优雅的解决方案吗?

感谢您的帮助,对不起,如果这是一个重复/愚蠢的问题

2 个答案:

答案 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。您可以轻松组合上面的两个表达式。您可能还想添加空引用检查。