C#Xml分组以获得更好的可视化效果

时间:2015-10-26 10:06:53

标签: c# xml linq

我有这个xml

<Group>
    <Day name="Mo">
        <title>Foo</title>
    </Day>
    <Day name="Tu">
        <title>Foo</title>
        <title>Bar</title>
    </Day>
    <Day name="We">
        <title>Foo</title>
    </Day>
    <Day name="Su">
        <title>Foo</title>
    </Day>
</Group>

我希望以这种方式转换这个xml

<Group>
    <Day name="Mo,Tu,We,Th,Su"> <!-- notice the repetition of tuesday -->
        <title>Foo</title>
    </Day>
    <Day name="Tu">
        <title>Bar</title>
    </Day>
</Group>

使用LINQ to XML进行更好的可视化。我知道这两个xml在逻辑上并不相同,但我已经实现了我的系统而不关心它。

我一直在尝试使用此LINQ查询对元素进行分组

var grp = from d in source.Element("Grp").Elements("Day")
          group d by new { name = d.Attribute("name"), value = d.Elements("title")
           into g
           select g;

但是我注意到我得到的东西与我开始的xml相同。

我对如何做到这一点有任何想法?

2 个答案:

答案 0 :(得分:0)

您按姓名分组&amp;标题,所以你得到的唯一独特的群体就是你已经拥有的那些。

您需要按标题对名称进行分组,然后您最终会得到包含一堆具有相同标题的名称的分组。

var groupings = from day in doc.Descendants("Day")
                let name = (string)day.Attribute("name")
                from title in day.Elements("title")
                group name by title.Value;

然后,您可以使用它们来创建一些新元素:

var elements = from grouping in groupings
               let title = grouping.Key
               let names = string.Join(",", grouping)
               select new XElement("Day",
                   new XAttribute("name", names),
                   new XElement("title", title)
                   );

然后只为这些元素创建一个新容器:

var result = new XDocument(
    new XElement("Group",
        elements
        )
    );

您可以在this fiddle中看到一个有效的例子。

答案 1 :(得分:0)

试试这个

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;


namespace ConsoleApplication53
{
    class Program
    {
        static void Main(string[] args)
        {
            string xml =
                "<Root>" + 
                    "<Group>" +
                        "<Day name=\"Mo\">" +
                            "<title>Foo</title>" +
                        "</Day>" +
                        "<Day name=\"Tu\">" +
                            "<title>Foo</title>" +
                            "<title>Bar</title>" +
                        "</Day>" +
                        "<Day name=\"We\">" +
                            "<title>Foo</title>" +
                        "</Day>" +
                        "<Day name=\"Su\">" +
                            "<title>Foo</title>" +
                        "</Day>" +
                    "</Group>" +
                 "</Root>";

            XElement root = XElement.Parse(xml);
            var groups = root.Descendants("Group").Elements("Day").Select(x => new
            {
                titles = x.Descendants("title").Select(y => new {
                   day = x.DescendantsAndSelf().FirstOrDefault(),
                   title = (string)y
                }).ToList()
            }).SelectMany(z => z.titles).GroupBy(a => a.title).Select(b => new XElement("Day", new object[] {
                    new XAttribute("name", string.Join(",", b.Select(c => c.day.Attribute("name").Value).ToArray())),
                    new XElement("title",b.FirstOrDefault().title)
                })).ToList();

            root.Element("Group").ReplaceWith(new XElement("Group", groups));




        }

    }
}