热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用LINQ将XML标记的集合连接到字符串-ConcatenatecollectionofXMLtagstostringwithLINQ

ImstuckwithusingawebserviceIhavenocontroloverandamtryingtoparsetheXMLreturnedby

I'm stuck with using a web service I have no control over and am trying to parse the XML returned by that service into a standard object.

我无法使用我无法控制的Web服务,并且正在尝试将该服务返回的XML解析为标准对象。

A portion of the XML structure looks like this

XML结构的一部分看起来像这样


   Some text here 
   Some additional text here 
   Still more text here 

In the end, I want to end up with one String property that will look like "Some text here Some additional text here Still more text here "

最后,我想最终得到一个String属性,看起来像“有些文本在这里一些额外的文字在这里还有更多的文字在这里”

What I have for an initial pass is what follows. I think I'm on the right track, but not quite there yet:

我对初始通行证的内容如下。我想我走在正确的轨道上,但还没到那里:

XElement source = \\Output from the Webservice
List 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
    }

I know that I could add a ToList() operator at the end of that query to return the collection. Is there an opertaor or technique that would allow me to inline the concatentation of that collection to a single string?

我知道我可以在该查询的末尾添加一个ToList()运算符来返回集合。是否有一个opertaor或技术允许我将该集合的连接内联到一个字符串?

Feel free to ask for more info if this isn't clear.

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

Thanks.

4 个解决方案

#1


LINQ to XML is indeed the way here:

LINQ to XML确实就是这样的方式:

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

var text = string.Join(" ", textArray);

EDIT: Based on the comment, it looks like you just need a single-expression way of representing this. That's easy, if somewhat ugly:

编辑:基于评论,看起来你只需要一种表达方式的单表达方式。这很容易,如果有点难看:

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())
    };

Another alternative is to extract it into a separate extension method (it has to be in a top-level static class):

另一种方法是将其提取为单独的扩展方法(它必须位于顶级静态类中):

public static string ConcatenateTextNodes(
    this IEnumerable elements)
{
    string[] values = elements.Select(x => x.Value).ToArray();
    // You could parameterise the delimiter here if you wanted
    return string.Join(" ", values);
}

then change your code to:

然后将您的代码更改为:

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 = indexentry.Elements("NO")
                         .Descendants()
                         .ConcatenateTextNodes()
    }

EDIT: A note about efficiency

编辑:关于效率的说明

Other answers have suggested using StringBuilder in the name of efficiency. I would check for evidence of this being the right way to go before using it. If you think about it, StringBuilder and ToArray do similar things - they create a buffer bigger than they need to, add data to it, resize it when necessary, and come out with a result at the end. The hope is that you won't need to resize too often.

其他答案建议在效率名称中使用StringBuilder。在使用它之前,我会检查这是正确的方法。如果你考虑一下,StringBuilder和ToArray会做类似的事情 - 他们创建一个比他们需要的更大的缓冲区,向它添加数据,在必要时调整它的大小,并在最后得出结果。希望你不需要经常调整大小。

The difference between StringBuilder and ToArray here is what's being buffered - in StringBuilder it's the entire contents of the string you've built up so far. With ToArray it's just references. In other words, resizing the internal buffer used for ToArray is likely to be cheaper than resizing the one for StringBuilder, particularly if the individual strings are long.

StringBuilder和ToArray之间的区别在于缓冲 - 在StringBuilder中它是你到目前为止构建的字符串的全部内容。使用ToArray它只是引用。换句话说,调整用于ToArray的内部缓冲区的大小可能比调整StringBuilder的大小更便宜,特别是如果单个字符串很长。

After doing the buffering in ToArray, string.Join is hugely efficient: it can look through all the strings to start with, work out exactly how much space to allocate, and then concatenate it without ever having to copy the actual character data.

在ToArray中执行缓冲之后,string.Join非常有效:它可以查看所有字符串以开始,确切地分配多少空间,然后连接它而无需复制实际的字符数据。

This is in sharp contrast to a previous answer I've given - but unfortunately I don't think I ever wrote up the benchmark.

这与我之前给出的答案形成鲜明对比 - 但不幸的是,我认为我没有写过基准。

I certainly wouldn't expect ToArray to be significantly slower, and I think it makes the code simpler here - no need to use side-effects etc, aggregation etc.

我当然不希望ToArray明显变慢,我认为它使代码更简单 - 不需要使用副作用等,聚合等。

#2


The other option is to use Aggregate()

另一种选择是使用Aggregate()

var q = topelement.Elements("L")
                  .Select(x => x.Value)
                  .Aggregate(new StringBuilder(), 
                             (sb, x) => return sb.Append(x).Append(" "),
                             sb => sb.ToString().Trim());

edit: The first lambda in Aggregate is the accumulator. This is taking all of your values and creating one value from them. In this case, it is creating a StringBuilder with your desired text. The second lambda is the result selector. This allows you to translate your accumulated value into the result you want. In this case, changing the StringBuilder to a String.

编辑:Aggregate中的第一个lambda是累加器。这将获取所有值并从中创建一个值。在这种情况下,它正在创建一个包含所需文本的StringBuilder。第二个lambda是结果选择器。这允许您将累积的值转换为您想要的结果。在这种情况下,将StringBuilder更改为String。

#3


I don't have experience with it myself, but it strikes me that LINQ to XML could vastly simplify your code. Do a select of XML document, then loop through it and use a StringBuilder to append the L element to some string.

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

#4


I like LINQ as much as the next guy, but you're reinventing the wheel here. The XmlElement.InnerText property does exactly what's being asked for.

LINQ和下一个人一样喜欢LINQ,但是你在这里重新发明轮子。 XmlElement.InnerText属性完全符合要求。

Try this:

using System.Xml;

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

推荐阅读
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 介绍平常在多线程开发中,总避免不了线程同步。本篇就对net多线程中的锁系统做个简单描述。目录一:lock、Monitor1:基础 ... [详细]
  • PriorityQueue源码分析
     publicbooleanhasNext(){returncursor<size||(forgetMeNot!null&am ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • LeetCode笔记:剑指Offer 41. 数据流中的中位数(Java、堆、优先队列、知识点)
    本文介绍了LeetCode剑指Offer 41题的解题思路和代码实现,主要涉及了Java中的优先队列和堆排序的知识点。优先队列是Queue接口的实现,可以对其中的元素进行排序,采用小顶堆的方式进行排序。本文还介绍了Java中queue的offer、poll、add、remove、element、peek等方法的区别和用法。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 本文介绍了OpenStack的逻辑概念以及其构成简介,包括了软件开源项目、基础设施资源管理平台、三大核心组件等内容。同时还介绍了Horizon(UI模块)等相关信息。 ... [详细]
  • 本文记录了在vue cli 3.x中移除console的一些采坑经验,通过使用uglifyjs-webpack-plugin插件,在vue.config.js中进行相关配置,包括设置minimizer、UglifyJsPlugin和compress等参数,最终成功移除了console。同时,还包括了一些可能出现的报错情况和解决方法。 ... [详细]
  • 本文介绍了在C#中SByte类型的GetHashCode方法,该方法用于获取当前SByte实例的HashCode。给出了该方法的语法和返回值,并提供了一个示例程序演示了该方法的使用。 ... [详细]
  • JVM:33 如何查看JVM的Full GC日志
    1.示例代码packagecom.webcode;publicclassDemo4{publicstaticvoidmain(String[]args){byte[]arr ... [详细]
author-avatar
Jin_木_木_176
这个家伙很懒,什么也没留下!
Tags | 热门标签
RankList | 热门文章
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有