Answered How to Sort XDocument Content by Node Name

  • Thursday, July 12, 2012 10:59 AM
     
      Has Code

    Hi folks,

    Please can you help with sorting elements in an xml file...I'm new to LINQ to XML.

    I have the following file:

    <my_elem>
       <Toms_elem>
          <Kates_elem />
          <Als_elem />
          <your_elem />
          <another_elem>
             <some_elem>
                <num3>13</num3>
                <num1>14</num1>
                <num2>15</num2>
             </some_elem>
          </another_elem>
          <sams_elem>
             <item_elem>
                <elem6>1</elem6>
                <elem4>2</elem4>
                <elem2>3</elem2>
                <elem1>4</elem1>
             </item_elem>
          </sams_elem>
       </Toms_elem>
       <dudes_elem>
          <Kates_elem />
          <Als_elem />
          <dummy_elem>
             <c_elem>cde</c_elem>
             <a_elem>abc</a_elem>
          </dummy_elem>
       </dudes_elem>
    </my_elem>

    I need all elements sorted by name, as follows:

    <my_elem>
       <dudes_elem>
          <Als_elem />
          <dummy_elem>
             <a_elem>abc</a_elem>
             <c_elem>cde</c_elem>
          </dummy_elem>
          <Kates_elem />
       </dudes_elem>
       <Toms_elem>
          <Als_elem />
          <another_elem>
             <some_elem>
                <num1>14</num1>
                <num2>15</num2>
                <num3>13</num3>
             </some_elem>
          </another_elem>
          <Kates_elem />
          <sams_elem>
             <item_elem>
                <elem1>4</elem1>
                <elem2>3</elem2>
                <elem4>2</elem4>
                <elem6>1</elem6>
             </item_elem>
          </sams_elem>
          <your_elem />
       </Toms_elem>
    </my_elem>

    I thought I could do it with LINQ to xml using something like this:

    XDocument xmldoc = XDocument.Load ("update.xml");
     
    IEnumerable<XElement> elems = from el in xmldoc.Elements ()
                                  orderby el.Name
                                  select el;
     
    xmldoc.ReplaceNodes (elems);
    

    but this returns the same exact doc as the original. What am I doing wrong? Please help.

    Many Thanks.

    Peter


All Replies

  • Thursday, July 12, 2012 11:16 AM
     
     Answered Has Code

    Well doc.Elements() where doc is an XDocument just selects the single root element where you can't change the order of a single element obviously. So you need to sort doc.Root.Elements() and as far as I can tell you also want to sort recursively on the children and descendants so I think you want

            static void Main(string[] args)
            {
                XDocument doc = XDocument.Load("input.xml");
                SortByName(doc.Root);
                doc.Save("output.xml");
            }
    
            static void SortByName(XContainer container)
            {
                container.ReplaceNodes(
                    from childEl in container.Elements()
                    orderby childEl.Name.LocalName
                    select childEl
                );
                foreach (XElement childEl in container.Elements())
                {
                    SortByName(childEl);
                }
            }
        }


    MVP Data Platform Development My blog

    • Proposed As Answer by Martin Honnen Thursday, July 12, 2012 12:16 PM
    • Marked As Answer by Piterrr Thursday, July 12, 2012 7:27 PM
    •  
  • Thursday, July 12, 2012 7:34 PM
     
     

    Thank you Martin.

    With your explanation I can see how my code would only sort the single root element...lol. Your code as written sorts everything alrigh, but it creates the new xml doc with all elements empty. Nevertheless, I was able to use it and adapt to my needs. Also thanks for bringing XContainer to the attention of my internal C# dictionary. :-) Appreciate it.

    Peter