использовать агрегатную функцию linq для построения XML-строки? - PullRequest
0 голосов
/ 02 ноября 2009

В прошлом я использовал это для создания разделенных запятыми списков:

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 ]

3 голосов
/ 02 ноября 2009

Ответ Блинди, безусловно, сработает, но я бы лично использовал:

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

Я лично считаю, что легче читать и понимать, чем агрегирование. Я верю, что это будет более эффективным, хотя это будет иметь значение только для больших списков.

3 голосов
/ 02 ноября 2009

Или есть более простой способ?

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 голосов
/ 02 ноября 2009

Не должно ли быть как:

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

Вы добавляете в a новые узлы.

0 голосов
/ 09 июля 2010

Есть несколько способов добиться этого, но я подозреваю, что правильный ответ - «это зависит». Ваш оригинальный пример для создания строки 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" при открытии или закрытии тегов, но я думаю об этом с точки зрения принципа СУХОЙ. Иногда я забывал изменить закрывающий тег для элемента, когда я изменил открывающий тег, например, в конфигурационных файлах. Использование 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 () выигрывает каждый раз (с довольно ограниченным / базовым тестовым примером Я использовал).

...