I have several times needed a way to sort XML, retrieved from a file or a web service, inline without invoking XSL transformations, which is the most common way to do it as I have seen.
The .NET Framework contains the System.Xml.XPath namespace and is available from the .NET Framework 1.1 and up. This namespace contains a number of classes which can improve the performance of your .NET classes when working with XML. Specifically the System.Xml.XPath.XPathExpression contains a method (System.Xml.XPath.XPathExpression.AddSort) to sort the XPath query results.
The code below shows you an easy way to sort your XML data based on this namespace.
This is the XML we will use:
<Entries>
<Entry id="1">
<Name>Hello</Name>
Entry>
Entry id="2">
Name>World</Name>
</Entry>
<Entry id="3">
<Name>Test</Name>
</Entry>
</Entries>
To sort this based on the Name element all we have to do is to create an XPathNavigator and add an XPath Expression with sorting like this:
XmlDocument doc = new XmlDocument();
doc.Load(@".\data.xml");
XPathNavigator navigator = doc.CreateNavigator();
XPathExpression expression = navigator.Compile("Entries/Entry");
expression.AddSort("Name", XmlSortOrder.Ascending, XmlCaseOrder.UpperFirst, string.Empty, XmlDataType.Text);
XPathNodeIterator iterator = navigator.Select(expression);
foreach (XPathNavigator item in iterator) {
Console.WriteLine(item.Value);
}
As you can see we create the XPathNavigator from the XmlDocument using the CreateNavigator method (which can be found on XmlNode and derivatives as well) and the create the expression with the sort and executes it using the Select method. Really simple!
To sort on the id attribute we change the AddSort method call to this:
expression.AddSort("@id", XmlSortOrder.Ascending, XmlCaseOrder.UpperFirst, string.Empty, XmlDataType.Number);
Notice the XmlDataType.Number value of the last parameter.
The sample above will work on the .NET Framework 2.0 and above, since it uses the GetEnumerator() method of the XPathNodeIterator class, which was introduced in 2.0.
To make it work in .NET 1.1 rewrite the foreach statement with something like this:
...
XPathNodeIterator iterator = navigator.Select(expression);
while(iterator.MoveNext()) {
Console.WriteLine(iterator.Current.Value);
}
Hope this one will help you doing crazy workarounds…
Update: changed typo in .NET 1.1. code sample…