问:对于一个 XML文件采用Ext框架,如何通过Ext提供的方法,实现对 XML结构的解析? 答:1.Ext采用例如Ext.da ta.JsonStore这样的store,传递url、root、fields、baseParams等参数,来获取数据 集。并且用服务器端的语言来解析XML返回{root:.......}形式的json。 2.包含XmlReader的普通store。 我们重点来讨论下这个XmlReader到底怎么用。 首先,我们得先解决这个棘手的问题: 怎么去拿到XML中的相应node和node的集合? 后台可以依靠XPath迅速的找到指定节点以及节点集合,Ext靠什么呢?靠的就是Ext.DomQuery。Ext的API中对它有详细的解释: 复杂的我们先不说,先看下面的这个XML: <conf> <country name="China"> <cid>China</cid> <province name="ShanXi"> <pid>ShanXi</pid> <city>TaiYuan</city> <city>DaTong</city> <city>YunCheng</city> </province> </country> <country name="America"> <cid>America</cid> <province name="Florida"> <pid>aaa</pid> <city>bbb</city> <city>ccc</city> <city>ddd</city> </province> </country> </conf> 那么store该怎么写呢? 1:如果要返回所有country的数据集合:
var store = new Ext.data.Store({ url: 'cpc.xml', reader: new Ext.data.XmlReader({ record: 'country', }, [ {name: 'country', mapping: 'cid'} ]) }); 2:如果要返回China下的省份数据集合: var store = new Ext.data.Store({ url: 'cpc.xml', reader: new Ext.data.XmlReader({ record: 'country[name=China] > province', }, [ {name: 'p', mapping: 'pid'} ]) }); 3:如果要返回某山西省下的所有城市: 可以吧XML改为如下的形式: <conf> <country name="China"> <cid>China</cid> <province name="ShanXi"> <pid>ShanXi</pid> <city> <cityid>TaiYuan</cityid> </city> <city> <cityid>DaTong</cityid> </city> <city> <cityid>YunCheng</cityid> </city> </province> .... .... </conf> store为: var store = new Ext.data.Store({ url: 'cpc.xml', reader: new Ext.data.XmlReader({ record: 'country[name=China] > province[name=ShanXi] > city', }, [ {name: 'c', mapping: 'cityid'} ]) }); 有人会说,我这样都把数据写死了。是的,要想动态的改变store的内容,我们需要借助Ext为我们提供的事件和相 应的方法。现在以combobox和grid联动为例: combobox显示国家名称,联动的grid里显示相应省份列表。 我们可以这样写: var combobox = ..........; var store = new Ext.data.Store({}); var grid = new Ext.grid.GridPanel({ store: store, columns: [ {header: "province", 120, dataIndex: 'p'} ], 540, height:200 }); combobox.on('select', function(combo){ var value = combo.getValue(); store = new Ext.data.Store({ url: 'cpc.xml', reader: new Ext.data.XmlReader({ record: 'country[name=' + value + '] > province', }, [ {name: 'p', mapping: 'pid'} ]); grid.reconfigure(store, grid.getColumnModel()); store.load(); }); 这里我们要注意几点: 1,注意gridpanel的reconfigure方法,它是改换store的好工具,换了后千万别忘了load一下store哦。 2,注意XML外面一定要包一层东西,就是上面的xml中的最外层<conf>,如果没有<conf>,是不可能取到国家数据集 的。 3,注意combo的mode一定要是remote啊。 4,注意例子中的XML很特殊,mapping貌似只能对应一个node的tag,好像不可以对应一个Node的属性,这点有达人知 道的话,回复一下在下。 5,用firebug可以看到,不管你取到的是哪一层数据,response的永远都是xml整个文件,数据量大的时候要慎重使 用XMLReader。(这点是废话,reader是在返回后调用的,只是一个解析器) 6,用XMLReader在我看来,会牺牲一下XML的“个性”,需要复合DOMQuery的检索规范。它显然没有后台的XPATH那么 强势,所以,我们在处理“细活”的时候最好利用后台代码。
<Lists> <List Name="ExecuteObject"> <Item Type="Page" Body="../WFBusinessFrame/WFFrame.aspx" Parameter="测试" __STATE="" __rowNo="0" /> </List> <List Name="Parameter" /> <List Name="Incoming"> <Item TaskId="ID10000" TaskName="办公用品申请" Method="" Condition="" /> <Item TaskId="ID10001" TaskName="IT经理审批" Method="" Condition="" /> </List>
</Lists>
Ext.define('Executorbody', { extend: 'Ext.data.Model', fields: [ // set up the fields mapping into the xml doc // The first needs mapping, the others are very basic {name: 'ListName', mapping: '@Name' }, {name: 'Type', mapping: 'Item > @Type' }, { name: 'Body', mapping: 'Item > @Body' }, { name: 'Parameter', mapping: '@Parameter' } ] }); var store = Ext.create('Ext.data.Store', { model: 'Executorbody', autoLoad: true, proxy: { // load using HTTP type: 'ajax', url: '/WebShare/Workflow/wfDefine.xml', // the return will be XML, so lets set up a reader reader: { type: 'xml', // records will have an "List" tag record: "Lists > List[Name='ExecuteObject']" } } }); this.grid = Ext.create('Ext.grid.Panel', { store: store, columns: [//配置表格列 Ext.create('Ext.grid.RowNumberer', { text: '行号', 35 }), { header: "ListName", 50, dataIndex: 'ListName', sortable: true, align: "center", editor: { xtype: 'textfield'} }, { header: "类别", 50, dataIndex: 'Type', sortable: true, align: "center", editor: { xtype: 'textfield'} }, { header: "执行体", 400, dataIndex: 'Body', sortable: true, align: "center", editor: { xtype: 'textfield'} }, { header: "参数", 60, dataIndex: 'Parameter', sortable: true, align: "right", editor: { xtype: 'textfield'} } ], 840, height: 200 });
-
剖析如下:
-
我们主要是从以下xml里取出
List Name ,Item里的 Type, Body,Parameter
<List Name="ExecuteObject"> <Item Type="Page" Body="../WFBusinessFrame/WFFrame.aspx" Parameter="测试" __STATE="" __rowNo="0" /> </List>
record: "Lists > List[Name='ExecuteObject']"
- 在例子里我们是搜索所有List里Name='ExecuteObject' 的记录,所以要用以下方式进行检索,注意
Name 是 List的属性
如果不需要过滤,直接用List就行
- 在例子里我们是搜索List,因此要想找到Type,body必须Mapping to 'Item > @Type'
- 由于对Parameter 没有指定路径,因此在 结果里没能显示,
{name: 'ListName', mapping: '@Name' }, {name: 'Type', mapping: 'Item > @Type' }, { name: 'Body', mapping: 'Item > @Body' }, { name: 'Parameter', mapping: '@Parameter' }
- 如果: 搜索Item, 如下,要想找到Type,body只需 Mapping to '@Type' 就行;
record: "Lists > List[Name='ExecuteObject']" > Item
-
Mapping时 不要带“@”
|