13.8 过滤和排序一个XMLListCollection集合
13.8.1 问题
需要对一个XMLListCollection过滤和排序
13.8.2解决
使用ListViewCollection类的filterFunction和sortFunction属性(XMLListCollection类扩展自该类)或者仅仅传递一个类型Sort的对象给XMLListCollections的sort属性。
13.8.3讨论
XMLListCollections描述XML数据,在根部含有多个节点。例如,包含在nutriton节点里的food项目集将被解释成XMLListCollection,使得这些food节点被看作一个集合。
<nutrition>
<food>
        <name>Avocado Dip</name>
        <calories>110</calories>
        <total-fat>11</total-fat>
        <saturated-fat>3</saturated-fat>
        <cholesterol>5</cholesterol>
        <sodium>210</sodium>
        <carb>2</carb>
        <fiber>0</fiber>
        <protein>1</protein>
</food>
...
</nutrition>

过滤XMLListCollection的方式和ArrayCollection相同:也是通过传递一个函数的引用,该函数接收一个Object作为参数,返回布尔值,用来决定是否该对象应该留在过滤后的视图中。例如:
coll.filterFunction = lowCalFilter;
private function lowCalFilter(value:Object):Boolean {
        if(Number(value.calories) < 200) {
                return true;
        }
        return false;
}

过滤XMLListCollection需要一个Sort对象,这个对象的fields数组属性需要设置为一些SortField对象。
var sort:Sort = new Sort();
sort.fields = [new SortField("calories", false, false, true)];
coll.sort = sort;
coll.refresh();


这里列出了演示XMLListCollection的完整的代码,代码包含HTTPService的调用,排序及过滤,如下:
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300"
creationComplete="xmlService.send()">
        <mx:HTTPService url="assets/data.xml" resultFormat="xml" id="xmlService" result=
"createXMLCollection(event)"/>
        <mx:Script>
                <![CDATA[
                        import mx.collections.SortField;
                        import mx.collections.Sort;
                        import mx.rpc.events.ResultEvent;
                        import mx.collections.XMLListCollection;

                        [Bindable]
                        private var coll:XMLListCollection;

                        private function createXMLCollection(event:ResultEvent):void {
                                var list:XMLList = new XMLList(event.result);
                                coll = new XMLListCollection(list.food);
                                var sort:Sort = new Sort();
                                sort.fields = [new SortField("calories", false, false, true)];
                                coll.sort = sort;
                                coll.refresh();
                            }

                     private function applyFilter():void {
                             coll.filterFunction = lowCalFilter;
                             coll.refresh();
                        }

                        private function lowCalFilter(value:Object):Boolean {
                                if(Number(value.calories) < 200) {
                                        return true;
                                }
                                return false;
                        }


                ]]>
        </mx:Script>
        <mx:DataGrid dataProvider="{coll}">
                        <mx:columns>
                                    <mx:DataGridColumn dataField="calories"/>
                                    <mx:DataGridColumn dataField="name"/>
                        </mx:columns>
        </mx:DataGrid>
        <mx:Button click="applyFilter()" label="filter"/>
</mx:VBox>

通过对XML集合中的不同节点使用E4X语句可以实现复杂的过滤;例如,通过如下所示的@语法访问属性:

private function lowFatFilter(value:Object):Boolean {
        if(value.calories(@fat) < Number(value.calories)/5) {
                    return true;
        }
        return false;
}

 
 
译者注:如果觉得老外的例子不是很好,改了改:
程序代码:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="xmlService.send()">
<mx:Style>
  Application{font-size:12px;}
</mx:Style>
<mx:HTTPService url="data.xml" resultFormat="xml" id="xmlService" result="createXMLCollection(event)"/>
        <mx:Script>
                <![CDATA[
                        import mx.collections.SortField;
                        import mx.collections.Sort;
                        import mx.rpc.events.ResultEvent;
                        import mx.collections.XMLListCollection;

                        [Bindable]
                        private var coll:XMLListCollection;

                        private function createXMLCollection(event:ResultEvent):void {
                                var list:XML = new XML(event.result);
                                coll = new XMLListCollection(list.student);
                                var sort:Sort = new Sort();
        
        //SortField(字段名=null,大小写不敏感?=false,降序?=false,Object是否按编号?=null)
                                sort.fields = [new SortField("total", false, true, true)];//降序
                                coll.sort = sort;
                                coll.refresh();//因为绑定,coll的变化引起DataGrid的刷新
                            }

                     private function applyFilter():void {
                             coll.filterFunction = myFilter;
                             coll.refresh();
                        }

        
                        private function myFilter(value:Object):Boolean {
                                if(Number(value.total) < 380) {
                                        return true;//保留总分<380,看看<380的都有哪些人
                                }
                                return false;
                        }


                ]]>
        </mx:Script>
        <mx:DataGrid dataProvider="{coll}">
                        <mx:columns>
                                    <mx:DataGridColumn headerText="姓名" dataField="name"/>
                                    <mx:DataGridColumn headerText="语文" dataField="chinese"/>
                                    <mx:DataGridColumn headerText="数学" dataField="math"/>
                                    <mx:DataGridColumn headerText="英语" dataField="english"/>
            <mx:DataGridColumn headerText="总分" dataField="total"/>
                        </mx:columns>
        </mx:DataGrid>
        <mx:Button click="applyFilter()" label="过滤"/>
</mx:Application>
 
data.xml:
 
<?xml version="1.0" encoding="utf-8" ?>
<students>
<student>
        <name>张三</name>
        <chinese>130</chinese>
        <math>140</math>
        <english>125</english>
        <total>395</total>
</student>
<student>
        <name>李四</name>
        <chinese>110</chinese>
        <math>138</math>
        <english>126</english>
        <total>374</total>
</student>
<student>
        <name>王五</name>
        <chinese>120</chinese>
        <math>125</math>
        <english>135</english>
        <total>380</total>
</student>
</students>

这里的total字段的值是钉死的,实际中可能会根据其他字段计算求和的。