ChekaZ ChekaZ - 2 months ago 10
C# Question

Sort XML file by attribute but keep the parent structure [dynamic]

The code looks like this:

<xx>
<xy>
<xz>
<xx somestring="bbb" value= "0"...>
<xx somestring="cad" value= "0"...>
<xx somestring="axa" value= "0"...>
<xx somestring="aaa" value= "0"...>
<xz>
<xy>
<xx>


This needs to be sorted by "somestring" alphabetical, the dept of the nodes is variable and the name of xx, xy, xz are also variable, the only thing that is always there is "somestring" which needs to be sorted in that way, but the order of the parents needs to keep the same. Just

Anyone able to help me out here? Would be awesome if done in LINQ.

Thanks in advance

Answer

Here is an example that sorts independent of the name of elements, simply by the value you select based on a Func<XElement, TKey>:

class Program
{
    static void Main(string[] args)
    {
        XDocument doc = XDocument.Load("../../XMLFile1.xml");
        doc.Root.Sort(el => (string)el.Attribute("bar"));
        doc.Save(Console.Out);
    }

}

public static class MyExt
{
    public static void Sort<TKey>(this XElement input, Func<XElement, TKey> selector)
    {
        input.Elements().ToList().ForEach(el => el.Sort(selector));
        input.ReplaceNodes(input.Elements().OrderBy(selector));
    }
}

With an input of

<?xml version="1.0" encoding="utf-8" ?>
<root>
  <section>
    <foo bar="az">
      <baz bar="c"/>
      <baz bar="b"/>
      <baz bar="a"/>
    </foo>
    <foo bar="am"/>
  </section>
  <section>
    <div>
      <value bar="x"/>
      <value bar="d"/>
      <value bar="a"/>
    </div>
  </section>
</root>

the output is

<root>
  <section>
    <foo bar="am" />
    <foo bar="az">
      <baz bar="a" />
      <baz bar="b" />
      <baz bar="c" />
    </foo>
  </section>
  <section>
    <div>
      <value bar="a" />
      <value bar="d" />
      <value bar="x" />
    </div>
  </section>
</root>

So for your sample you would use doc.Root.Sort(el => (string)el.Attribute("somestring"));.

Comments