I have a XML Structure that looks like this.
-
There's an overload of XPathExpression.Addsort which takes an IComparer interface. If you implement the comparison yourself as IComparer, you could use this mechanism.
class Program
{
static void Main(string[] args)
{
XPathDocument saleResults = new XPathDocument( @"salesData.xml" );
XPathNavigator navigator = saleResults.CreateNavigator( );
XPathExpression selectExpression = navigator.Compile( "sales/item" );
XPathExpression sortExpr = navigator.Compile("@sTime");
selectExpression.AddSort(sortExpr, new DateTimeComparer());
XPathNodeIterator nodeIterator = navigator.Select( selectExpression );
while ( nodeIterator.MoveNext( ) )
{
string checkMe = nodeIterator.Current.Value;
}
}
public class DateTimeComparer : IComparer
{
public int Compare(object x, object y)
{
DateTime dt1 = DateTime.Parse( x.ToString( ) );
DateTime dt2 = DateTime.Parse( y.ToString( ) );
return dt1.CompareTo( dt2 );
}
}
}
Here you go:
XmlDocument myDoc = new XmlDocument();
myDoc.LoadXml(@"
<sales>
<item name=""Games""
sku=""MIC28306200""
iCat=""28""
sTime=""11/26/2008 8:41:12 AM""
price=""1.00""
desc=""Item Name"" />
<item name=""Games""
sku=""MIC28307100""
iCat=""28""
sTime=""11/26/2008 8:42:12 AM""
price=""1.00""
desc=""Item Name"" />
</sales>
");
var sortedItems = myDoc.GetElementsByTagName("item").OfType<XmlElement>()
.OrderBy(item => DateTime.ParseExact(item.GetAttribute("sTime"), "MM/dd/yyyy h:mm:ss tt", null));
foreach (var item in sortedItems)
{
Console.WriteLine(item.OuterXml);
}
That's a Console app that works perfectly.
suppose ur date time is in this format
2010-06-01T15:16:29+05:00
then simplest way that can be done is
< xsl:sort select="translate(XPATH_RETURNING_DATE,'-T:+','')" order="descending" data-type="number" />
IN DATETIME JUST REPLACE EXTRA CHARACTERS in my datetime format i have the extra characters ( - T : and + ) so just replace it AND THEN YOUR DATE TIME WILL BE IN NUMBER FORMAT THAT CAN BE SORTED EASILY
What you're trying to do is accomplished a lot more easily if the XML is properly constructed. The XML Schema recommendation says that date/time values should be represented in ISO8601 format, i.e. CCCC-MM-DD HH:MM:SS
. (Actually XML Schema wants the separator between date and time to be a T, and at the moment I don't remember why.)
The two principal advantages of formatting dates and times this way are:
It's a cruelty to format dates any other way in XML that's going to be processed by XSLT.
It's easy enough to make .NET emit DateTime values in this format (use the "s" format specifier, which stands for - wait for it - "sortable").
I know this Question is quite old and you probably have a solution with you but i like to share my answer:
private static void SortElementAttributesBasis(XmlNode rootNode)
{
for (int j = 0; j < rootNode.ChildNodes.Count; j++)
{
for (int i = 1; i < rootNode.ChildNodes.Count; i++)
{
Console.WriteLine(rootNode.OuterXml);
DateTime dt1 = DateTime.ParseExact(rootNode.ChildNodes[i].Attributes["sTime"].Value, "M/d/yyyy h:mm:ss tt", System.Globalization.CultureInfo.InvariantCulture);
DateTime dt2 = DateTime.ParseExact(rootNode.ChildNodes[i-1].Attributes["sTime"].Value, "M/d/yyyy h:mm:ss tt", System.Globalization.CultureInfo.InvariantCulture);
int compare = DateTime.Compare(dt1,dt2);
if (compare < 0)
{
rootNode.InsertBefore(rootNode.ChildNodes[i], rootNode.ChildNodes[i - 1]);
Console.WriteLine(rootNode.OuterXml);
}
// Provide the name of Attribute in .Attribute["Name"] based on value you want to sort.
//if (String.Compare(rootNode.ChildNodes[i].Attributes["sTime"].Value, rootNode.ChildNodes[1 - 1].Attributes["sTime"].Value) < 0)
//{
// rootNode.InsertBefore(rootNode.ChildNodes[i], rootNode.ChildNodes[i - 1]);
//}
}
}
}
Input XML is sample provided by @Dimitre Novatchev
<sales>
<item name="Games" sku="MIC28306200" iCat="28"
sTime="11/26/2008 8:41:12 PM"
price="1.00" desc="Item Name" />
<item name="Games" sku="MIC28307100" iCat="28"
sTime="11/26/2008 8:42:12 AM"
price="1.00" desc="Item Name" />
<item name="Games" sku="MIC28307100" iCat="28"
sTime="11/26/2008 11:42:12 AM"
price="1.00" desc="Item Name" />
<item name="Games" sku="MIC28306200" iCat="28"
sTime="12/23/2008 8:41:12 PM"
price="1.00" desc="Item Name" />
<item name="Games" sku="MIC28307100" iCat="28"
sTime="12/23/2008 8:42:12 AM"
price="1.00" desc="Item Name" />
Output
<item name="Games" sku="MIC28307100" iCat="28" sTime="11/26/2008 8:42:12 AM" price="1.00" desc="Item Name" /><item name="Games" sku="MIC28307100" iCat="28" sTime="11/26/2008 11:42:12 AM" price="1.00" desc="Item Name" /><item name="Games" sku="MIC28306200" iCat="28" sTime="11/26/2008 8:41:12 PM" price="1.00" desc="Item Name" /><item name="Games" sku="MIC28307100" iCat="28" sTime="12/23/2008 8:42:12 AM" price="1.00" desc="Item Name" />
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:template match="sales"> <sales> <xsl:for-each select="item"> <xsl:sort select="substring(@sTime,7,4)" data-type="number"/> <xsl:sort select="substring(@sTime,1,2)" data-type="number"/> <xsl:sort select="substring(@sTime,4,2)" data-type="number"/> <xsl:sort select="substring-after(substring-after(@sTime,' '),' ')" /> <xsl:sort data-type="number" select= "translate( substring-before(substring-after(@sTime,' '),' '), ':', '' ) " /> <xsl:copy-of select="."/> </xsl:for-each> </sales> </xsl:template> </xsl:stylesheet>
When this transformation is applied on the following XML document:
<sales> <item name="Games" sku="MIC28306200" iCat="28" sTime="11/26/2008 8:41:12 PM" price="1.00" desc="Item Name" /> <item name="Games" sku="MIC28307100" iCat="28" sTime="11/26/2008 8:42:12 AM" price="1.00" desc="Item Name" /> <item name="Games" sku="MIC28307100" iCat="28" sTime="11/26/2008 11:42:12 AM" price="1.00" desc="Item Name" /> <item name="Games" sku="MIC28306200" iCat="28" sTime="12/23/2008 8:41:12 PM" price="1.00" desc="Item Name" /> <item name="Games" sku="MIC28307100" iCat="28" sTime="12/23/2008 8:42:12 AM" price="1.00" desc="Item Name" /> </sales>
the correct result is produced:
<sales> <item name="Games" sku="MIC28307100" iCat="28" sTime="11/26/2008 8:42:12 AM" price="1.00" desc="Item Name"/> <item name="Games" sku="MIC28307100" iCat="28" sTime="11/26/2008 11:42:12 AM" price="1.00" desc="Item Name"/> <item name="Games" sku="MIC28306200" iCat="28" sTime="11/26/2008 8:41:12 PM" price="1.00" desc="Item Name"/> <item name="Games" sku="MIC28307100" iCat="28" sTime="12/23/2008 8:42:12 AM" price="1.00" desc="Item Name"/> <item name="Games" sku="MIC28306200" iCat="28" sTime="12/23/2008 8:41:12 PM" price="1.00" desc="Item Name"/> </sales>