Sorting all the elements in a XDocument

前端 未结 4 607
孤城傲影
孤城傲影 2020-12-10 02:56

I have a XDocument where I\'d like to sort all of the elements alphabetically. Here\'s a simplified version of the structure:


 
         


        
相关标签:
4条回答
  • 2020-12-10 03:12

    Here is an updated example that will include all attributes when performing the 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));
    }
    

    This post helped me a lot, because I did not want to perform an XML sort using XSLT since I did not want to reformat the XML. I searched all around for a simple solution to perform an XML sort using C# and ASP.NET and I was delighted when I found this thread. Thanks to all, this did exactly what I needed.

    0 讨论(0)
  • 2020-12-10 03:13

    You already have a method to sort the elements. Just apply it recursively:

    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));
    }
    

    Note that this strips all non-element nodes (attributes, text, comments, etc.) from your document.


    If you want to keep the non-element nodes, you have to copy them over:

    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));
    }
    
    0 讨论(0)
  • 2020-12-10 03:21

    I think these extension method work best.

    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<XElement> 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<XAttribute> sortedAttributes = source.Attributes().OrderBy(a => a.ToString()).ToList();
         sortedAttributes.ForEach(a => a.Remove());
         sortedAttributes.ForEach(a => source.Add(a));
      }
    }
    
    0 讨论(0)
  • 2020-12-10 03:25

    THIS METHOD MAKES A REAL DOCUMENT EXTENSION AND PRESERVES THE ATTRIBUTES AND TEXT VALUES

    I came up with this based off a few different posts and code from here and there... Thanks to all who contributed!

    Within the same namespace (not the same class) add the following...

    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<XAttribute> 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<XElement> 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));
        }
    }
    

    To use the document extension...

    //Load the xDoc
    XDocument xDoc = XDocument.Load("c:\test.xml");
    
    //Sort the root element
    xDoc.Root.Sort();
    
    0 讨论(0)
提交回复
热议问题