使用linq聚合函数来构建xml字符串?

时间:2009-11-01 21:04:16

标签: xml linq aggregate csv

我过去曾用过这个来构建逗号分隔列表:

var list = new List<int>{1,2,3};
var retVal = list.Select(i=>i.ToString()).Aggregate((a,b) => a+", "+b);

效果很好。

我正在尝试将每个元素“包装”为xml节点。

类似的东西:

Aggregate((a, b) => string.Format("<ID>{0}</ID><ID>{1}</ID>", a,b))

但似乎无法让它发挥作用。可能吗?或者是否有更简单的方法?

感谢。

4 个答案:

答案 0 :(得分:3)

Blindy的回答肯定会奏效,但我个人会用:

var list = new List<int> {1, 2, 3};
var joined = string.Join("", list.Select(x => "<ID>" + x + "</ID>")
                                 .ToArray());

我个人觉得比聚合更容易阅读和理解。我相信它也会更有效率 - 尽管这只会对大型列表有用。

答案 1 :(得分:3)

  

或者是否有更简单的方法?

List<int> list = new List<int>{1, 2, 3};
var xmlNodes = list.Select(i => new XElement("ID", i));
XElement xml = new XElement("Data", xmlNodes);
Console.WriteLine(xml);

答案 2 :(得分:2)

不应该是这样的:

Aggregate((a, b) => string.Format("{0}<ID>{1}</ID>", a,b))

您正在添加a个新节点。

答案 3 :(得分:0)

有很多方法可以达到这个目的,但我怀疑正确答案是“它取决于”。您创建CSV字符串的原始示例使用字符串连接运算符;建议的方法是使用 StringBuilder 类来实现此目的。在.Net 4.0中, string.Join()方法有一个新的重载,使用和理解起来更加简单。

// .Net 3.5
var list = new List<int>{1,2,3};
var csv = list.Aggregate(new StringBuilder(), 
    (sb, i) => sb.Append(i).Append(','),
    sb => { if (sb.Length > 0) sb.Length--; return sb.ToString(); });

// .Net 4.0
var csv1 = string.Join(",", list);

如果您的目的是创建XML文档而不是字符串,那么David B上面的答案是一个不错的选择:

var xml = new XElement("Root", list.Select(i => new XElement("ID", i)));
// <Root>
//   <ID>1</ID>
//   <ID>2</ID>
//   <ID>3</ID>
// </Root> 

为了创建XML字符串,我宁愿避免显式编码开始和结束标记。在你的例子中,在开始或结束标签中很难得到元素名称“ID”,但我想到了DRY原则。有时我忘记在修改开始标记时修改元素的结束标记,例如在配置文件中。使用 XElement 完全避免了这个问题:

// .Net 3.5
var xml1 = list.Aggregate(new StringBuilder(), 
           (sb, i) => sb.Append(new XElement("ID", i)),
           sb => sb.ToString());

// .Net 4.0
var xml2 = string.Join("", list.Select (i => new XElement("ID", i)));
// both xml1 & xml2 contain "<ID>1</ID><ID>2</ID><ID>3</ID>"

Aggregate() string.Join() string.Join()的性能每次都获胜(相当有限/我使用过的基本测试用例。