B2.
B2.

Reputation: 83

Change order of XML using XDocument

I want to change the order of XML using XDocument

<root>
  <one>1</one>
  <two>2</two>
</root>

I want to change the order so that 2 appears before 1. Is this capability baked in or do I have to do it myself. For example, remove then AddBeforeSelf()?

Thanks

Upvotes: 8

Views: 8398

Answers (4)

podeig
podeig

Reputation: 2741

Try this solution...

XElement node = ...get the element...

//Move up
if (node.PreviousNode != null) {
    node.PreviousNode.AddBeforeSelf(node);
    node.Remove();
}

//Move down
if (node.NextNode != null) {
    node.NextNode.AddAfterSelf(node);
    node.Remove();
}

Upvotes: 3

Germ&#225;n
Germ&#225;n

Reputation:

Similar to above, but wrapping it in an extension method. In my case this works fine for me as I just want to ensure a certain element order is applied in my document before the user saves the xml.

public static class XElementExtensions
{
    public static void OrderElements(this XElement parent, params string[] orderedLocalNames)
    {            
        List<string> order = new List<string>(orderedLocalNames);            
        var orderedNodes = parent.Elements().OrderBy(e => order.IndexOf(e.Name.LocalName) >= 0? order.IndexOf(e.Name.LocalName): Int32.MaxValue);
        parent.ReplaceNodes(orderedNodes);
    }
}
// using the extension method before persisting xml
this.Root.Element("parentNode").OrderElements("one", "two", "three", "four");

Upvotes: 6

Jeff Yates
Jeff Yates

Reputation: 62357

Outside of writing C# code to achieve this, you could use XSLT to transform the XML.

Upvotes: 1

smaclell
smaclell

Reputation: 4658

This should do the trick. It order the child nodes of the root based on their content and then changes their order in the document. This is likely not the most effective way but judging by your tags you wanted to see it with LINQ.

static void Main(string[] args)
{
    XDocument doc = new XDocument(
        new XElement("root",
            new XElement("one", 1),
            new XElement("two", 2)
            ));

    var results = from XElement el in doc.Element("root").Descendants()
                  orderby el.Value descending
                  select el;

    foreach (var item in results)
        Console.WriteLine(item);

    doc.Root.ReplaceAll( results.ToArray());

    Console.WriteLine(doc);

    Console.ReadKey();
}

Upvotes: 1

Related Questions