基于DateTime属性C#,XPath对XML节点进行排序

我有一个看起来像这样的XML结构。

   ...  

我试图找到一种方法来根据sTime属性SORT节点,这是一个DateTime.ToString()值。 诀窍是我需要保持节点的机智,由于某种原因,我找不到办法做到这一点。 我很确定LINQ和XPath有办法做到这一点,但我被卡住了,因为我似乎无法根据DateTime.ToString()值进行排序。

 XPathDocument saleResults = new XPathDocument(@"temp/salesData.xml"); XPathNavigator navigator = saleResults.CreateNavigator(); XPathExpression selectExpression = navigator.Compile("sales/item/@sTime"); selectExpression.AddSort("@sTime", XmlSortOrder.Descending, XmlCaseOrder.None, "", XmlDataType.Number); XPathNodeIterator nodeIterator = navigator.Select(selectExpression); while( nodeIterator.MoveNext() ) { string checkMe = nodeIterator.Current.Value; } 

我还需要维护一个指向NODE的指针来检索其他属性的值。

也许这并不像我想的那么简单。

谢谢。

解决方案 :这是我最终使用的内容。 获取所选答案和IComparable类,这就是我如何根据sTime属性对XML节点进行排序,然后将所有属性放入相应的Arrays中以便稍后使用。

  XPathDocument saleResults = new XPathDocument(@"temp/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); int i = 0; while (nodeIterator.MoveNext()) { if (nodeIterator.Current.MoveToFirstAttribute()) { _iNameList.SetValue(nodeIterator.Current.Value, i); } if (nodeIterator.Current.MoveToNextAttribute()) { _iSkuList.SetValue(nodeIterator.Current.Value, i); } ... nodeIterator.Current.MoveToParent(); i++; } 

XPathExpression.Addsort超载,它采用IComparer接口。 如果您自己将比较实现为IComparer,则可以使用此机制。

  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 ); } } } 

干得好:

 XmlDocument myDoc = new XmlDocument(); myDoc.LoadXml(@"     "); var sortedItems = myDoc.GetElementsByTagName("item").OfType() .OrderBy(item => DateTime.ParseExact(item.GetAttribute("sTime"), "MM/dd/yyyy h:mm:ss tt", null)); foreach (var item in sortedItems) { Console.WriteLine(item.OuterXml); } 

这是一个完美运行的控制台应用程序。

这是一个XSLT解决方案:

 
  

     
       <销售>
         
           
           
           
           
           
           
         
     
 

将此转换应用于以下XML文档时

 <销售>
     
     
     
     
     
 

产生了正确的结果:

 <销售>
    
    
    
    
    
 

如果正确构造XML,那么您正在尝试做的事情会轻松完成。 XML Schema建议说日期/时间值应以ISO8601格式表示,即CCCC-MM-DD HH:MM:SS 。 (实际上,XML Schema希望日期和时间之间的分隔符为T,而此刻我不记得原因。)

以这种方式格式化日期和时间的两个主要优点是:

  • 这就是XML的其他用户所期望的,以及
  • 您可以对其字符串值进行排序。

在XSLT处理的XML中以任何其他方式格式化日期是一种残酷的做法。

使.NET以这种格式发出DateTime值很容易(使用“s”格式说明符,代表 – 等待它 – “可排序”)。

假设你的日期时间是这种格式

2010-06-01T15:16:29 + 05:00

那么最简单的方法就是

在DATETIME中我只能以我的日期时间格式替换额外的字符我有额外的字符( – T:和+)所以只需更换它然后您的日期时间将是数字格式,可以轻松排序

我知道这个问题很老,你可能有一个解决方案,但我想分享我的答案:

  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]); //} } } } 

输入XML是由@Dimitre Novatchev提供的示例

       

产量