tags:

views:

495

answers:

4

I have a Xml Document and it is contains some date datas like;

<Message>
<messagetext>Testing purpose only</messagetext>
<date>05.02.2010</date>
</Message>

I want them sorted with a XPath key, how can I get if anyone knows about pls help me

thanks all regards

+1  A: 

You can do it using LINQ to XML as follows. I assume you are using the format MM.dd.yyyy, but this can easily be changed if you want:

using System;
using System.Linq;
using System.Xml.Linq;

public class Message
{
    public string Text { get; set; }
    public DateTime Date { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        XDocument doc = XDocument.Load("input.xml");
        var messages = doc.Descendants("Message")
            .Select(element => new Message
            {
                Text = element.Element("messagetext").Value,
                Date = DateTime.ParseExact(element.Element("date").Value, "MM.dd.yyyy", null)
            }).OrderBy(message => message.Date);
        foreach (Message message in messages)
        {
            Console.WriteLine("{0} : {1}", message.Date, message.Text);
        }
    }
}

Results:

02-05-2010 00:00:00 : Test1
17-05-2010 00:00:00 : Test2
22-05-2010 00:00:00 : Test3

Test data I used:

<xml>
  <Message>
    <messagetext>Test1</messagetext>
    <date>05.02.2010</date>
  </Message>
  <Message>
    <messagetext>Test3</messagetext>
    <date>05.22.2010</date>
  </Message>
  <Message>
    <messagetext>Test2</messagetext>
    <date>05.17.2010</date>
  </Message>
</xml>
Mark Byers
i have got .net 2.0 on my server so i cant use LINQ.
Ibrahim AKGUN
A: 

First of all XPath isn't going to help do any sorting except as part of an XSLT transform. Secondly XPath 1.0 as used in .NET does not have any date specific support.

The easiest approach would be to load the XML into an XDocument and use code like this (assumes a series of "Message" nodes under to toplevel root node in a document):-

Func<XElement, DateTime> fn = e => DateTime.ParseExact(e.Element("date").Value, "dd.MM.yyyy", CultureInfo.InvariantCulture);

var messages = doc.Root.Elements("Message").OrderBy(fn);

foreach (var elem in messages)
{
    Console.WriteLine(fn(elem));
}

Alternatively if you have reason to stick with XmlDocument this slightly uglier code will work:-

Func<XmlElement, DateTime> fn = e => DateTime.ParseExact(e.SelectSingleNode("date").InnerText, "dd.MM.yyyy", CultureInfo.InvariantCulture);

var messages = doc.DocumentElement.SelectNodes("Message")
    .Cast<XmlElement>().OrderBy(fn);


foreach (var elem in messages)
{
    Console.WriteLine(fn(elem));
}
AnthonyWJones
i have got .net 2.0 on my server so i cant use LINQ
Ibrahim AKGUN
@Ibrahim: Windows 2000? Or is there something else preventing you installing 3.5?
AnthonyWJones
i cant access and install anything.Server is Windows 2008 :)
Ibrahim AKGUN
@Ibrahim: If its Windows 2008 is has .NET 3.5. You perhaps may think it only has .NET 2.0 because the Application pool .NET Framework Version doesn't have a 3.5 option. However this field is mis-named (imo) it should say .NET CLR version. .NET 3.5 still uses the 2.0 CLR. On a Windows 2008 box you should find that .NET 3.5 is already present.
AnthonyWJones
thanx i ll check it up. than ll answer you
Ibrahim AKGUN
A: 

If you have control over the format of the XML, I'd recommend changing the date format to ISO 8601. That way, the dates can be sorted like regular strings. For example, 05.02.2010 would be 2010-05-02. Additionally, ISO 8601 is less ambiguous (month before day or day before month?)

Jacob
+3  A: 

The XPathExpression class allows you to add sort specifications. Here is some sample code that should work with .NET 2.0:

XPathDocument doc = new XPathDocument(@"..\..\XMLFile1.xml");
XPathNavigator nav = doc.CreateNavigator();
XPathExpression exp = nav.Compile("Messages/Message");
exp.AddSort(
  "number(concat(substring(date, 7), substring(date, 4, 2), substring(date, 1, 2)))",
  XmlSortOrder.Descending, 
  XmlCaseOrder.None, 
  null, 
  XmlDataType.Number
);
foreach (XPathNavigator msg in nav.Select(exp))
{
  Console.WriteLine(
    "{0}: {1}", 
    msg.SelectSingleNode("date").Value, 
    msg.SelectSingleNode("messagetext").Value
  );
}

With XMLFile1.xml being

<Messages>
  <Message>
    <messagetext>Message 2</messagetext>
    <date>04.02.2010</date>
  </Message>
  <Message>
    <messagetext>Message 1</messagetext>
    <date>05.02.2010</date>
  </Message>
  <Message>
    <messagetext>Message 3</messagetext>
    <date>05.02.2009</date>
  </Message>
</Messages>

the output is

05.02.2010: Message 1
04.02.2010: Message 2
05.02.2009: Message 3

Assumed date format is ddmmyyyy but you could change those substring expressions as needed if you want mmddyyyy.

Martin Honnen
+1 Hey Martin welcome to StackOverflow its good to see you here. Where ya been at? I was expecting to see you here with your excellent XML answers a long time ago. ;)
AnthonyWJones