【问题标题】:Using LINQ to surround all "group" elements with the new element "groups" in C#使用 LINQ 在 C# 中用新元素“组”包围所有“组”元素
【发布时间】:2011-03-01 16:44:58
【问题描述】:

我是 LINQ 和 C# 的新手,但我有一个从数据库表生成的 xml 文件。 XML 文档中有一个名为“group”的元素,我想用名为“groups”的元素包装所有 group 元素。

XML 文档的摘录是:

<members>
- <user>
  <fullname>John Smith</fullname> 
  <username>SmithA</username> 
  <email>John.smith@test.com/email> 
  <distinguishedName>xxx</distinguishedName> 
  <group>London</group>
  </user>
- <user>
  <fullname>Sue Jones</fullname> 
  <username>JonesS</username> 
  <email>Sue.Jones@test.com/email> 
  <distinguishedName>xxx</distinguishedName> 
  <group>London</group>
  </user>
</members>

我在 C# ASP.NET 中努力编写代码的最终结果是:

<members>
- <user>
  <fullname>John Smith</fullname> 
  <username>SmithA</username> 
  <email>John.smith@test.com/email> 
  <distinguishedName>xxx</distinguishedName> 
  <groups>
  <group>London</group>
  <groups>
  </user>
- <user>
  <fullname>Sue Jones</fullname> 
  <username>JonesS</username> 
  <email>Sue.Jones@test.com/email> 
  <distinguishedName>xxx</distinguishedName> 
  <groups>
  <group>London</group>
  <groups>
  </user>
</members>

我们将不胜感激。

【问题讨论】:

    标签: c# asp.net xml linq


    【解决方案1】:

    认为这就是你想要的——它似乎对我有用:

    using System;
    using System.Linq;
    using System.Xml.Linq;
    
    class Program
    {
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load("test.xml");
            var groupedGroups = doc.Descendants("group")
                       .GroupBy(x => x.Parent);
    
            foreach (var groupedGroup in groupedGroups)
            {
                // Create the new element (copies each <group>)
                groupedGroup.Key.Add(new XElement("groups", groupedGroup));
    
                // Remove all the old ones
                foreach (var element in groupedGroup)
                {
                    element.Remove();
                }
            }
            Console.WriteLine(doc);
        }
    }
    

    为这个名字道歉 - 当每个概念都是“组”时,很难想出名字:)

    【讨论】:

    • Jon 我不清楚这里是否需要分组(即GroupBy的用法)。
    • @Ahmad:将所有具有单个父元素的&lt;group&gt; 元素组合在一个&lt;groups&gt; 元素中。
    【解决方案2】:

    一种方法是:

    1. 遍历每个user 元素
    2. 添加新的groups 元素
    3. 将现有的group 添加到新的groups 元素中
    4. 删除原来的group元素

    如果xmlXElement,则此方法与此类似:

    foreach (var user in xml.Elements("user"))
    {
        user.Add(new XElement("groups", user.Element("group")));
        user.Element("group").Remove(); 
    }
    

    如果您使用的是XDocument,则可以改用xml.Root.Elements("user")


    编辑:响应您的评论,如果 XML 包含多个编号的组,您可以过滤所有以“组”开头的元素并执行几乎相同的操作。
    foreach (var user in xml.Elements("user"))
    {
        var groups = user.Elements()
                         .Where(e => e.Name.LocalName.StartsWith("group"))
                         .ToArray();
    
        // rename groups
        foreach (var group in groups)
            group.Name = "group";
    
        user.Add(new XElement("groups", groups));
        groups.Remove();
    }
    

    请注意,我使用ToArray() 来防止Remove 调用重新评估表达式,这将错误地删除新添加的groups 元素,因为它也与以“组”开头的条件相匹配。另一种解决方法是更改​​Where 谓词以检查名称是否以数字结尾。防止意外选择可能以“组”开头的任何其他元素是额外的工作,但这取决于您对 XML 结构的了解。

    【讨论】:

    • 请注意,这只会处理每个用户的单个组元素。我假设 OP 想要处理多个元素 - 尽管如果示例包含此内容会很好。
    • @Jon 这是我对 OP 的理解。我想我在几秒钟前对你发表评论也是因为不够清晰。
    • 如果原始 XML 文档在每个需要被 group 元素包围的用户元素中包含 group1、group2、group3、groupx 元素怎么办?您是否在将元素附加到新组元素的循环中执行多个循环或循环?
    • 或者是否有可以在 doc.Descendants() 中使用的过滤器来选择所有以字符串“group”开头的元素?
    • @Mjakda 查看我的更新。您可以使用Where 子句进行过滤。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-26
    • 1970-01-01
    • 2019-05-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多