开发者

use linq aggregate function to build xml string?

I've used this in the past to build comma seperated lists:

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

Works great.

I'm trying to do the same sort of 开发者_如何转开发thing to 'wrap' each element as an xml node.

Something like:

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

Can't quite seem to make it work though. Is it possible? Or is there an easier way entirely?

Thanks.


Blindy's answer will certainly work, but I'd personally use:

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

I personally find that easier to read and understand than the aggregation. I believe it will be more efficient, too - although that will only matter for large lists.


Or is there an easier way entirely?

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


Shouldn't it be like:

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

You're adding to a new nodes.


There are a number of ways to achieve this but I suspect the correct answer is "it depends". Your original example for creating a CSV string uses the string concatenation operator; the recommended approach is to use the StringBuilder class for this purpose. And in .Net 4.0 there is a new overload for the string.Join() method that is a whole lot simpler to use and understand.

// .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);

If your intention is to create an XML Document rather than a string then David B's answer above is a good option:

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

For creating XML strings I prefer to avoid explicitly coding opening and closing tags. In your example it would be difficult to get the element name "ID" incorrect in either opening or closing tags but I think of this in terms of the DRY principle. On occasion I have forgotten to modify the closing tag for an element when I have modified the opening tag e.g. in config files. Using XElement avoids this issue completely:

// .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>"

Performance of Aggregate() versus string.Join(), string.Join() wins every time (with the fairly limited/basic test case I used).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜