Sorting an XML file

by Codewiz51 November 09, 2011 11:22

I needed to sort an xml file based on an attribute rather than a tag value.  This proved to be a little more subtle problem than I first imagined.  I've worked up a simple example of what is required to sort an xml file on an attribute value:

// FYI, there is a build event that copies the item dictionary to the correct
// directory.  If you get a run time error because the dictionary is missing,
// you need to check the output of the build event.

using System;
using System.Xml;
using System.Xml.XPath;

namespace XMLSort
{
    class Program
    {
        static void Main(string [ ] args)
        {
            // Create an xml doc instance and load the item dictionary

            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(@"ItemDictionary.xml");

            // Creeat the sorted document place holder

            XmlDocument xmlSortedDoc = new XmlDocument();

            // Copy the dictionary structure by loading the outer xml from doc

            xmlSortedDoc.LoadXml(xmlDoc.OuterXml);

            // remove the unsorted nodes

            xmlSortedDoc.SelectSingleNode("//items").RemoveAll();

            // Select the items node

            XmlNode node = xmlDoc.SelectSingleNode("//items");

            // Create an xpath navigator object

            XPathNavigator navigator = node.CreateNavigator();

            // Now the fun begins.  We want to navigate the item nodes.
            // There are four nodes in the itemdictionary.xml file.

            XPathExpression selectExpression = navigator.Compile("item");

            // Finally!  We get to define the sort conditions.
            // In this case, I want to sort on the name attribute of the item tag.

            selectExpression.AddSort("@name", XmlSortOrder.Ascending, XmlCaseOrder.None, "", XmlDataType.Text);

            // We need to create an iterator to loop through the nodes.
            // This allows us to create the inner xml item elements for
            // the sorted document

            XPathNodeIterator nodeIterator = navigator.Select(selectExpression);

            // Loop through the iterator, adding the nodes to the sorted document

            while ( nodeIterator.MoveNext() )
            {
                // Clone the iterator so we do not lose position

                XPathNavigator clone = nodeIterator.Current.Clone();

                // Try to move to name attribute

                if ( clone.MoveToFirstAttribute() )
                {

                    // Select the node from the xml document

                    XmlNode linkNode = xmlDoc.SelectSingleNode("//item[@name=\"" + clone.Value + "\"]");

                    // Copy the node by importing it to a temporary node

                    XmlNode importedLinkNode = xmlSortedDoc.ImportNode(linkNode, true);

                    // Select the items node, then append the imported node as a child

                    xmlSortedDoc.SelectSingleNode("//items").AppendChild(importedLinkNode);
                }
                else
                {
                    Console.WriteLine("Skipping node.");
                }
            }

            // Save the sorted dictionary to a new file

            xmlSortedDoc.Save(@"SortedItemDictionary.xml");
        }
    }
}

Here's the VS 2010 project, which includes the itemdictionary.xml file used in the example:

XMLSort.7z (7.75 kb)

Comments are closed

Powered by BlogEngine.NET 1.6.0.0
Theme by Mads Kristensen | Modified by Mooglegiant

Disclaimer

This blog represents my personal hobby, observations and views. It does not represent the views of my employer, clients, especially my wife, children, in-laws, clergy, the dog, the cats or my daughter's horse. In fact, I am not even sure it represents my views when I take the time to reread postings.

© Copyright 2008-2011