7

私はこのようなXML構造を持っています。

<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>

DateTime.ToString()値であるsTime属性に基づいてノードをSORTする方法を見つけようとしています。秘訣は、ノードを無傷に保つ必要があり、何らかの理由でそれを行う方法を見つけることができないことです。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ノードを並べ替えて、後で使用するためにすべての属性を適切な配列に取得する方法です。

    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++;

      }
4

6 に答える 6

5

どうぞ:

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

これは完全に機能するコンソール アプリです。

于 2008-12-05T18:52:12.637 に答える
4

IComparerインターフェイスを使用するXPathExpression.Addsortのオーバーロードがあります。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 );
                }
            }
        }
于 2008-12-05T18:39:28.120 に答える
2

XSLT ソリューションは次のとおりです。

<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="売上">
      <販売>
        <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=
           "翻訳(
               substring-before(substring-after(@sTime,' '),' '),
               ':', ''
                      )
               " />
          <xsl:copy-of select="."/>
        </xsl:for-each>
      </セールス>
    </xsl:テンプレート>
</xsl:スタイルシート>

この変換が次の XML ドキュメントに適用される場合:

<販売>
    <item name="ゲーム" sku="MIC28306200" iCat="28"
          sTime="2008/11/26 8:41:12 PM"
          price="1.00" desc="商品名" />
    <item name="ゲーム" sku="MIC28307100" iCat="28"
          sTime="2008/11/26 8:42:12 AM"
                price="1.00" desc="商品名" />
    <item name="ゲーム" sku="MIC28307100" iCat="28"
          sTime="2008/11/26 11:42:12 AM"
                price="1.00" desc="商品名" />
    <item name="ゲーム" sku="MIC28306200" iCat="28"
          sTime="12/23/2008 8:41:12 PM"
          price="1.00" desc="商品名" />
    <item name="ゲーム" sku="MIC28307100" iCat="28"
          sTime="2008/12/23 8:42:12 AM"
                price="1.00" desc="商品名" />
</セールス>

正しい結果が生成されます。

<販売>
   <item name="ゲーム" sku="MIC28307100" iCat="28" sTime="11/26/2008 8:42:12 AM" price="1.00" desc="アイテム名"/>
   <item name="ゲーム" sku="MIC28307100" iCat="28" sTime="11/26/2008 11:42:12 AM" price="1.00" desc="アイテム名"/>
   <item name="Games" sku="MIC28306200" iCat="28" sTime="11/26/2008 8:41:12 PM" price="1.00" desc="アイテム名"/>
   <item name="Games" sku="MIC28307100" iCat="28" sTime="12/23/2008 8:42:12 AM" price="1.00" desc="アイテム名"/>
   <item name="Games" sku="MIC28306200" iCat="28" sTime="12/23/2008 8:41:12 PM" price="1.00" desc="アイテム名"/>
</セールス>
于 2008-12-05T21:04:13.803 に答える
1

XMLが適切に構築されていれば、あなたがやろうとしていることははるかに簡単に達成されます。XMLスキーマの推奨事項では、日付/時刻の値はISO8601形式で表す必要があるとされていますCCCC-MM-DD HH:MM:SS。(実際、XMLスキーマでは、日付と時刻の間の区切り文字をTにする必要がありますが、現時点ではその理由を覚えていません。)

この方法で日付と時刻をフォーマットする2つの主な利点は次のとおりです。

  • これは、XMLの他のユーザーが期待していることです。
  • 文字列値で並べ替えることができます。

XSLTによって処理されるXMLで日付を他の方法でフォーマットすることは、残酷です。

.NETにこの形式でDateTime値を出力させるのは簡単です(「s」形式指定子を使用します。これは「待機」を意味します)。

于 2008-12-05T19:30:44.493 に答える
0

この質問はかなり古いものであり、おそらく解決策があることは承知していますが、私の答えを共有したいと思います:

      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 が提供するサンプルです。

<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" />

出力

<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" />

于 2017-09-25T10:16:28.400 に答える
0

あなたの日時がこの形式であると仮定します

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

次に、実行できる最も簡単な方法は

< xsl:sort select="translate(XPATH_RETURNING_DATE,'-T:+','')" order="descending" data-type="number" />

IN DATETIME JUST REPLACE EXTRA CHARACTERS in my datetime format 余分な文字 ( - T : と + ) があるので、それを置き換えるだけで、日時は簡単にソートできる数値形式になります

于 2010-06-24T11:19:17.480 に答える