【问题标题】:How to use XDocument and Linq to read in a list of parent attribute concatenated with child comment如何使用 XDocument 和 Linq 读取与子注释连接的父属性列表
【发布时间】:2016-05-07 07:04:36
【问题描述】:

我是 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")

我已经尝试将 cmets 和 ids 读取到两个不同的列表中,然后将它们组合起来,但这不是一个足够好的解决方案,因为在我的现实世界问题中,可能存在没有注释名称的服务。

我目前的解决方案是这样的:

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 循环并将它们连接起来。一定有更优雅的解决方案?

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

【问题讨论】:

    标签: c# xml linq parsing xml-parsing


    【解决方案1】:

    这应该可行。

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

    【讨论】:

      【解决方案2】:

      这是一种可能的方式:

      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
      

      【讨论】:

      • 谢谢大家,我会在星期一试试这些。我严重怀疑如果没有大量阅读 Linq,我会得到这些,所以再次感谢。
      • 这两个都有效,我从你的答案中学到了很多,非常感谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-13
      • 2018-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-16
      相关资源
      最近更新 更多