对XDocument中的所有元素进行排序

我有一个XDocument,我想按字母顺序对所有元素进行排序。 这是结构的简化版本:

  svr1  route1  1   7200    HD1         

我想在各个级别对这些文档中的元素进行排序,到目前为止我能够像这样对它进行排序:

 private static XDocument Sort(XDocument file) { return new XDocument( new XElement(file.Root.Name, from el in file.Root.Elements() orderby el.Name.ToString() select el)); } 

哪个产生:

        svr1  route1  1   7200    HD1    

我希望能够以相同的方式对所有子元素进行排序(理想情况下通过递归函数)。 任何想法我怎么能用LINQ得到这个?

谢谢你的任何想法。

您已经有了一种方法来对元素进行排序。 只需递归应用它:

 private static XElement Sort(XElement element) { return new XElement(element.Name, from child in element.Elements() orderby child.Name.ToString() select Sort(child)); } private static XDocument Sort(XDocument file) { return new XDocument(Sort(file.Root)); } 

请注意,这会从文档中删除所有非元素节点(属性,文本,注释等)。


如果要保留非元素节点,则必须将它们复制到:

 private static XElement Sort(XElement element) { return new XElement(element.Name, element.Attributes(), from child in element.Nodes() where child.NodeType != XmlNodeType.Element select child, from child in element.Elements() orderby child.Name.ToString() select Sort(child)); } private static XDocument Sort(XDocument file) { return new XDocument( file.Declaration, from child in file.Nodes() where child.NodeType != XmlNodeType.Element select child, Sort(file.Root)); } 

这种方法可以实现真正的文档扩展并保留属性和文本值

我想出了这个基于几个不同的post和代码来自这里和那里…感谢所有谁贡献!

在同一个命名空间(不是同一个类)中添加以下内容……

 public static void Sort(this XElement source, bool bSortAttributes = true) { //Make sure there is a valid source if (source == null) throw new ArgumentNullException("source"); //Sort attributes if needed if (bSortAttributes) { List sortedAttributes = source.Attributes().OrderBy(a => a.ToString()).ToList(); sortedAttributes.ForEach(a => a.Remove()); sortedAttributes.ForEach(a => source.Add(a)); } //Sort the children IF any exist List sortedChildren = source.Elements().OrderBy(e => e.Name.ToString()).ToList(); if (source.HasElements) { source.RemoveNodes(); sortedChildren.ForEach(c => c.Sort(bSortAttributes)); sortedChildren.ForEach(c => source.Add(c)); } } 

要使用文档扩展名…

 //Load the xDoc XDocument xDoc = XDocument.Load("c:\test.xml"); //Sort the root element xDoc.Root.Sort(); 
 private static XElement Sort(XElement element) { XElement newElement = new XElement(element.Name, from child in element.Elements() orderby child.Name.ToString() select Sort(child)); if (element.HasAttributes) { foreach (XAttribute attrib in element.Attributes()) { newElement.SetAttributeValue(attrib.Name, attrib.Value); } } return newElement; } private static XDocument Sort(XDocument file) { return new XDocument(Sort(file.Root)); } 

这是一个更新的示例,其中包括执行排序时的所有属性。

这篇文章对我帮助很大,因为我不想使用XSLT执行XML排序,因为我不想重新格式化XML。 我搜索了一个简单的解决方案,使用C#和ASP.NET执行XML排序,当我找到这个post时,我很高兴。 感谢所有人,这完全符合我的需要。

〜马特

我认为这些扩展方法效果最好。

 public static class XmlLinq { public static void Sort(this XElement source, bool sortAttributes = true) { if (source == null) throw new ArgumentNullException("source"); if (sortAttributes) source.SortAttributes(); List sortedChildren = source.Elements().OrderBy(e => e.Name.ToString()).ToList(); source.RemoveNodes(); sortedChildren.ForEach(c => source.Add(c)); sortedChildren.ForEach(c => c.Sort()); } public static void SortAttributes(this XElement source) { if (source == null) throw new ArgumentNullException("source"); List sortedAttributes = source.Attributes().OrderBy(a => a.ToString()).ToList(); sortedAttributes.ForEach(a => a.Remove()); sortedAttributes.ForEach(a => source.Add(a)); } }