ホーム >> 左脳Script >> Adobe Flash >> Action Script >> XML でソートするには

XML でソートするには


XMLの内容をソートするメソッドというものは存在しません。Arrayのようにデータ構造が単純ではない為、データに合う実装方法を製作者側が明示的に記述する必要があり、その頻度が高い為に一般化できないのです。

しかし、現実問題 XML でデータを扱えば、「ソート」や「ソートした上で最初の10件」等、データベース的な処理が必要になる場合が多いです。
その度に「もしかしたら良い方法があるんではなかろうか」と検索する訳ですが、何度やっても便利メソッドすら見つけられないのです。

流石に物覚えの悪い私でも「そんなモノはにぃ!」事が判ってきました。


それならば、せめてソート処理に"即した"方法をテンプレ化とは言いませんが、一般化出来ないものかと考えて見ました。


ソート

今まで何度かやってきた事を簡単に説明すると、
  1. XMLList → Array 」変換。
  2. Array.sort や Array.map 等でソート等の処理をした配列にする。
  3. 「 Array → XMLList 」変換。
と、まぁ、順当な物になります。上記の1番目3番目の変換に使えそうな便利メソッドが無いか検索してみましたが、ソレっぽものはありませんでした。

更に「先頭から何件」という条件が付く場合、上記の2番目と3番目の間に、
  • Array.length 切り詰め。
が入ります。


コード例

XML 変数 honge は 属性 date と属性 length を持った child タグを多数保持しているとします。

var honge:XML =<items>
    <child date="12345678" length="80">全自動冷蔵庫</child>
    <child date="12334458" length="8000">V6ツインカムターボ搭載炊飯ジャー</child>
    <child date="12345850" length="200">ジャイロ式オートアシスト付アイロン</child>
    <child date="12548855" length="255">核磁気共鳴チョコレート</child>
    <child date="13568943" length="0">寒冷地仕様扇風機</child>
    <child date="12357807" length="2000">完全防水(2000気圧)目覚まし時計</child>
    <child date="13457678" length="160">エアバック装備チェスト</child>
    <child date="12346678" length="1970">イギリス製フードプロセッサ(1970年製)</child>
    <child date="15680976" length="46">コピープロテクト対応オーディオカセットテープ(46分)</child>
    <child date="12548855" length="255">1UPきのこの里</child>
</items>;

  1. XMLList → Array 」変換。
    
    /**
     * XML 変数 honge から、childタグを列挙。
     */
    var childList:XMLList = honge.child;
    /**
     * 各要素を配列 ary へ。
     */
    var ary:Array = new Array();
    for each(var child:XML in childList)
    {
        ary.push(child);
    }
    
  2. Array.sort や Array.map 等でソート等の処理をした配列にする。
    
    ary.sort(function (a:XML,b:XML):int
    {
        //  date属性が小さい順にソート
        var dateA:Number = Number(a.@date);
        var dateB:Number = Number(b.@date);
        if (    dateA > dateB   )   return  1;
        if (    dateA < dateB   )   return  -1;
        //  date属性が同じ場合は、length属性の大きい順に。
        var lengthA:Number = Number(a.@length);
        var lengthB:Number = Number(b.@length);
        if (    lengthA > lengthB   )   return  -1;
        if (    lengthA < lengthB   )   return  1;
        //  属性が全て同じ場合は、中のテキスト長の短い順に。
        var strlenA:int = String(a).length;
        var strlenB:int = String(b).length;
        if (    strlenA > strlenB   )   return  1;
        if (    strlenA < strlenB   )   return  -1;
        //  全て同じ場合は、順序が変わらない。
        return  0;
    });
    
    Array.sort については、こちらを参照。

  3. 先頭から5件。
    
    ary.length = 5;
    

    後ろから5件の場合。しかし、この場合は、ソート条件を見直すべき。
    
    ary.reverse();
    ary.length = 5;
    ary.reverse();
    

  4. 「 Array → XMLList 」変換。
    
    var newHonge:XML = <items/>;
    newHonge.appendChild(
        new XMLList(
            ary.map(
                function (child:XML, index:int, arr:Array):String
                {
                    return child.toXMLString();
                }
            ).join("")
        )
    );
    
    この記述に関する詳細はこちら

先頭5件での実行結果。

<items>
  <child date="12334458" length="8000">V6ツインカムターボ搭載炊飯ジャー</child>
  <child date="12345678" length="80">全自動冷蔵庫</child>
  <child date="12345850" length="200">ジャイロ式オートアシスト付アイロン</child>
  <child date="12346678" length="1970">イギリス製フードプロセッサ(1970年製)</child>
  <child date="12357807" length="2000">完全防水(2000気圧)目覚まし時計</child>
</items>

後ろから5件での実行結果。

<items>
  <child date="12548855" length="255">1UPきのこの里</child>
  <child date="12548855" length="255">核磁気共鳴チョコレート</child>
  <child date="13457678" length="160">エアバック装備チェスト</child>
  <child date="13568943" length="0">寒冷地仕様扇風機</child>
  <child date="15680976" length="46">コピープロテクト対応オーディオカセットテープ(46分)</child>
</items>


この例にて、もしも honge に以下のような childタグ があると・・・

    <child delete="1"/>
ソートの段階で、@dete へアクセスが出来ずエラーが発生・・・するかと思いきや、そうはなりません。

属性への単純アクセスなので、E4X(ECMAScript for XML) による XML のフィルタリングとは違い、存在しない属性へのアクセスは null が返ってくるだけのようです。 したがって、上記のノードは「date="0" length="0"」(sort内関数で、Numberキャストされている為)という扱いで処理が進みます。


まと・・・め?

  1. XMLList → Array 」変換。
  2. Array.sort や Array.map 等でソート等の処理をした配列にする。
  3. 必要件数で Array.length 切り詰め。
  4. 「 Array → XMLList 」変換。

これで、バッチ・・り・・・だと、思うよ?タブン。              ←詰めが弱気な草食系



トラックバック(0)

トラックバックURL: http://n-yagi.0r2.net/sanoupulurun/mt-tb.cgi/253

コメントする

ホーム >> 左脳Script >> Adobe Flash >> Action Script >> XML でソートするには

アーカイブ

このブログ記事について

このページは、n-yagiが2010年1月21日 08:37に書いたブログ記事です。

ひとつ前のブログ記事は「配列の添え字についての検証」です。

次のブログ記事は「HTMLコントロールのリンクイベント」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

Creative Commons License
このブログはクリエイティブ・コモンズでライセンスされています。