C# 使用LINQ将XML标记集合连接到字符串

C# 使用LINQ将XML标记集合连接到字符串,c#,linq,linq-to-xml,C#,Linq,Linq To Xml,我一直在使用一个我无法控制的web服务,并试图将该服务返回的XML解析为一个标准对象 XML结构的一部分如下所示 <NO> <L>Some text here </L> <L>Some additional text here </L> <L>Still more text here </L> </NO> 这里有一些文字 这里有一些附加文本 这里还有更多的文字 最后,我希望得到

我一直在使用一个我无法控制的web服务,并试图将该服务返回的XML解析为一个标准对象

XML结构的一部分如下所示

<NO>
   <L>Some text here </L>
   <L>Some additional text here </L>
   <L>Still more text here </L>
</NO>

这里有一些文字
这里有一些附加文本
这里还有更多的文字
最后,我希望得到一个字符串属性,它看起来像“这里有一些文本,这里有一些附加文本,这里还有更多文本”

我第一次通过的是接下来的内容。我想我走的是对的,但还不完全正确:

XElement source = \\Output from the Webservice
List<IndexEntry> result;

result = (from indexentry in source.Elements(entryLevel)
    select new IndexEntry()
    {
        EtiologyCode = indexentry.Element("IE") == null ? null : indexentry.Element("IE").Value,
        //some code to set other properties in this object
        Note = (from l in indexentry.Elements("NO").Descendants
                select l.value)  //This is where I stop
                               // and don't know where to go
    }
XElement source=\\Webservice的输出
列出结果;
结果=(来自source.Elements(entryLevel)中的indexentry)
选择新IndexEntry()
{
EtiologyCode=indexentry.Element(“IE”)==null?null:indexentry.Element(“IE”).Value,
//一些代码用于设置此对象中的其他属性
注=(从indexentry.Elements(“NO”)子体中的l开始)
选择l.value)//这是我停止的地方
//不知道该去哪里
}
我知道我可以在该查询的末尾添加一个ToList()运算符来返回集合。是否有一种运算符或技术允许我将集合的concatation内联到单个字符串中

如果不清楚,请随时询问更多信息


谢谢。

我自己没有使用它的经验,但我觉得它可以大大简化您的代码。选择XML文档,然后循环使用它,并使用StringBuilder将L元素附加到某个字符串。

我自己没有使用它的经验,但我觉得它可以大大简化您的代码。选择XML文档,然后循环遍历它,并使用StringBuilder将L元素附加到某个字符串。

LINQ to XML确实是这里的方法:

var textArray = topElement.Elements("L")
                          .Select(x => x.Value)
                          .ToArray();

var text = string.Join(" ", textArray);
编辑:根据评论,您似乎只需要一种表达方式。这很简单,尽管有点难看:

result = (from indexentry in source.Elements(entryLevel)
    select new IndexEntry
    {
        EtiologyCode = indexentry.Element("IE") == null 
                           ? null 
                           : indexentry.Element("IE").Value,
        //some code to set other properties in this object
        Note = string.Join(" ", indexentry.Elements("NO")
                                          .Descendants()
                                          .Select(x => x.Value)
                                          .ToArray())
    };
另一种选择是将其提取到单独的扩展方法中(它必须位于顶级静态类中):

编辑:关于效率的说明

其他答案建议以效率的名义使用
StringBuilder
。在使用它之前,我会检查是否有证据表明这是正确的方法。如果你仔细想想,
StringBuilder
ToArray
也会做类似的事情-它们会创建一个比需要大的缓冲区,向其中添加数据,必要时调整大小最后给出一个结果。希望你不需要经常调整大小

StringBuilder
ToArray
之间的区别在于缓冲的内容-在
StringBuilder
中,它是您迄今为止构建的字符串的全部内容。使用
ToArray
它只是引用。换句话说,调整
ToArray
使用的内部缓冲区的大小可能更便宜而不是调整
StringBuilder
的大小,特别是当单个字符串较长时

ToArray
中进行缓冲后,
string.Join
非常有效:它可以查看所有要开始的字符串,精确计算要分配的空间,然后连接它,而不必复制实际的字符数据

这是在-但不幸的是,我不认为我写了基准


我当然不希望ToArray的速度会慢得多,而且我认为这使代码在这里变得更简单-无需使用副作用等,聚合等。

LINQ to XML确实是这里的方式:

var textArray = topElement.Elements("L")
                          .Select(x => x.Value)
                          .ToArray();

var text = string.Join(" ", textArray);
编辑:根据评论,您似乎只需要一种表达方式。这很简单,尽管有点难看:

result = (from indexentry in source.Elements(entryLevel)
    select new IndexEntry
    {
        EtiologyCode = indexentry.Element("IE") == null 
                           ? null 
                           : indexentry.Element("IE").Value,
        //some code to set other properties in this object
        Note = string.Join(" ", indexentry.Elements("NO")
                                          .Descendants()
                                          .Select(x => x.Value)
                                          .ToArray())
    };
另一种选择是将其提取到单独的扩展方法中(它必须位于顶级静态类中):

编辑:关于效率的说明

其他答案建议以效率的名义使用
StringBuilder
。在使用它之前,我会检查是否有证据表明这是正确的方法。如果你仔细想想,
StringBuilder
ToArray
也会做类似的事情-它们会创建一个比需要大的缓冲区,向其中添加数据,必要时调整大小最后给出一个结果。希望你不需要经常调整大小

StringBuilder
ToArray
之间的区别在于缓冲的内容-在
StringBuilder
中,它是您迄今为止构建的字符串的全部内容。使用
ToArray
它只是引用。换句话说,调整
ToArray
使用的内部缓冲区的大小可能更便宜而不是调整
StringBuilder
的大小,特别是当单个字符串较长时

ToArray
中进行缓冲后,
string.Join
非常有效:它可以查看所有要开始的字符串,精确计算要分配的空间,然后连接它,而不必复制实际的字符数据

这是在-但不幸的是,我不认为我写了基准


我当然不希望ToArray的速度明显变慢,我认为这会使代码更简单-无需使用副作用等,聚合等。

另一种选择是使用聚合()


编辑:聚合中的第一个lambda是累加器。这将获取所有值并从中创建一个值。在这种情况下,它将使用所需文本创建StringBuilder。第二个lambda是结果选择器。这允许您将累积值转换为所需的结果。在本cas中e、 将StringBuilder更改为字符串。

另一个选项是使用聚合()

编辑:第一个lambda
var q = topelement.Elements("L")
                  .Select(x => x.Value)
                  .Aggregate(new StringBuilder(), 
                             (sb, x) => return sb.Append(x).Append(" "),
                             sb => sb.ToString().Trim());
using System.Xml;

class Program
{
    static void Main(string[] args)
    {
        XmlDocument d = new XmlDocument();
        string xml =
            @"<NO>
  <L>Some text here </L>
  <L>Some additional text here </L>
  <L>Still more text here </L>
</NO>";
        d.LoadXml(xml);
        Console.WriteLine(d.DocumentElement.InnerText);
        Console.ReadLine();
    }
}