C# 使用Linq对XML进行分组,层次结构不正确

C# 使用Linq对XML进行分组,层次结构不正确,c#,xml,linq,treeview,C#,Xml,Linq,Treeview,我正在尝试解决如何从asp.net C中的sql查询创建treeview菜单。作为学习练习,我有一个包含过去三年假期的数据库-我想创建一个treeview,显示按年份排序的假期。例如,年->假日名称->假日日期,其中->表示分层级别 无论如何,我将使用以下查询从SQL以XML文档的形式返回我的假期: SELECT [Year], [Holiday], [Date] FROM [Database] FOR XML PATH('Holiday'), ROOT('Holidays') 当然,这将返

我正在尝试解决如何从asp.net C中的sql查询创建treeview菜单。作为学习练习,我有一个包含过去三年假期的数据库-我想创建一个treeview,显示按年份排序的假期。例如,年->假日名称->假日日期,其中->表示分层级别

无论如何,我将使用以下查询从SQL以XML文档的形式返回我的假期:

SELECT  [Year], [Holiday], [Date] FROM [Database] FOR XML PATH('Holiday'), ROOT('Holidays')
当然,这将返回一个没有分组的XML文档,因此我使用Linq将我的假期按年份分组,同时数据来自数据库,如下所示:

XmlReader reader = sqlCommand.ExecuteXmlReader();

    if (reader.Read())
    {
        XElement doc = XElement.Load(reader);
        var newData =
            new XElement("Holidays",
                from data in doc.Elements("Holiday")
                group data by (int)data.Element("Year") into groupedData
                select new XElement("Group",
                    new XAttribute("ID", groupedData.Key),
                    from g in groupedData
                    select new XElement("Holiday",
                        g.Element("Name"),
                        g.Element("Date")
                    )
                )
            );
这样更好:它按年份对我的假期进行分组,但我的树状视图最终显示如下:

2012
    Holiday
        Christmas Eve
        12/24/12
    Holiday
        Christmas Day
        12/25/12
    Holiday
        New Year's Eve
        12/31/12

。。。等等我是Linq的新手,所以我不确定在这里该做什么。我想去掉这个假日级别,将实际日期作为假日名称的子节点。我无法对SQL查询执行任何操作,因为XML只能有一个根节点。有什么想法吗?

更改您的select语句

   select new XElement(
                            g.Element("Name").Value,
                            g.Element("Date")
                        )

由于树显然使用XElement的ID属性作为树节点标签,因此如果存在此类属性,则可以将假日名称添加为假日节点的ID属性,而不是嵌套属性:

            if (reader.Read())
            {
                var doc = XElement.Load(reader);
                var newData =
                    new XElement("Holidays",
                        from data in doc.Elements("Holiday")
                        group data by (int)data.Element("Year") into groupedData
                        select new XElement("Group",
                            new XAttribute("ID", groupedData.Key),
                            from g in groupedData
                            select new XElement("Holiday", new XAttribute("ID", g.Element("Name").Value), g.Element("Date"))
                        )
                    );
                var newXml = newData.ToString();
                Debug.WriteLine(newXml);
            }
对于以下输入:

<?xml version="1.0" encoding="UTF-8"?>
<Holidays>
    <Holiday>
        <Name>Christmas Eve</Name>
        <Date>12/24/12</Date>
        <Year>2012</Year>
    </Holiday>
    <Holiday>
        <Name>Christmas</Name>
        <Date>12/25/12</Date>
        <Year>2012</Year>
    </Holiday>
    <Holiday>
        <Name>New Year's Eve</Name>
        <Date>12/31/12</Date>
        <Year>2012</Year>
    </Holiday>
</Holidays>
这将提供以下输出:

<Holidays>
  <Group ID="2012">
    <Holiday ID="Christmas Eve">
      <Date>12/24/12</Date>
    </Holiday>
    <Holiday ID="Christmas">
      <Date>12/25/12</Date>
    </Holiday>
    <Holiday ID="New Year's Eve">
      <Date>12/31/12</Date>
    </Holiday>
  </Group>
</Holidays>

注意,您不能将假日名称用作XElement名称,因为某些假日名称包含空格。

关闭,但这只会使我的树的第二级和第三级查看日期,即2012->12/24/12->12/24/12。应该是2012年->圣诞夜->12/24/12您没有解释XML在树中的显示方式,但我从代码中推断,如果元素具有属性ID,那么将显示该属性ID;否则,将显示XElement.Value。对吗?这就是我想要的结果。非常感谢你的帮助。