善待自己,珍惜今天,恩泽他人,享受生活

不放弃任何解决困难的机会,人的一生就是解决困难的过程。 当我们走完一生才能说没有问题要解决了。 面对工作、生活上的压力,面对来自家庭、朋友、同事、上司等的困惑。 要排除万难,否则我们就会被万难排除!

博客园 首页 新随笔 联系 订阅 管理

Extjs中,用XmlReader可以很方便地读取xml文件数据显示在GridPanel中。需要注意是不同结构xml,取值方式有所不同。如果取节点子节点内容,则直接写子节点名称;若取节点属性,则是符号@加属性名称;若取节点内容,则留空即可。举2个例子如下:
  如果我们要读取xml数据都在节点子节点,比如:

 

<Item>
<Author>Sidney Sheldon</Author>
<Title>Master of the Game</Title>
<Manufacturer>Warner Books</Manufacturer>
<ProductGroup>Book</ProductGroup>
</Item>

  则XmlReader中mapping直接写子节点名称或令name与子节点名称一致,则mapping可忽略,如下:

var store = new Ext.data.Store({
 url: ‘sheldon.xml’,
 reader: new Ext.data.XmlReader({
   record: ‘Item’
  }, [
   {name: 'Author', mapping: 'Author'},
   {name: 'Title'},
   'Manufacturer',
   'ProductGroup'
  ])
});

  如果我们要读取xml数据有是节点内容有是节点属性,比如:

XML语言: 知蚁博客

<Item Author=“Sidney Sheldon” Manufacturer=“Warner Books” ProductGroup=“Book”>Master of the Game</Item>

  则XmlReader中mapping写法如下:

{name: ‘Author’, mapping: ‘@Author’}, //取节点属性
{name: ‘Manufacturer’, mapping: ‘@Manufacturer’},
{name: ‘ProductGroup’, mapping: ‘@ProductGroup’}
{name: ‘Title’, mapping: ”}, //取节点内容

  用XmlReader读取xml文件很方便吧,O(∩_∩)O~

问:对于一个XML文件采用Ext框架,如何通过Ext提供的方法,实现对XML结构的解析?
        答:1.Ext采用例如Ext.data.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", width: 120, dataIndex: 'p'}
],
width: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那么
强势,所以,我们在处理“细活”的时候最好利用后台代码。
 
举个实际中的里子:
 
  • XML如下:

<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: '行号', width: 35 }),
                { header: "ListName", width: 50, dataIndex: 'ListName', sortable: true, align: "center", editor: { xtype: 'textfield'} },
                { header: "类别", width: 50, dataIndex: 'Type', sortable: true, align: "center", editor: { xtype: 'textfield'} },
                { header: "执行体", width: 400, dataIndex: 'Body', sortable: true, align: "center", editor: { xtype: 'textfield'} },
                { header: "参数", width: 60, dataIndex: 'Parameter', sortable: true, align: "right", editor: { xtype: 'textfield'} }
                ],
          
            width: 840,
            height: 200
        });

 
  • 呈现结果如下:

 
image
 
  • 剖析如下:

  •  

    我们主要是从以下xml里取出

    List Name ,Item里的 Type, Body,Parameter

<List Name="ExecuteObject">
<Item Type="Page" Body="../WFBusinessFrame/WFFrame.aspx" Parameter="测试" __STATE="" __rowNo="0" />
</List>

 

  • 所以定义的record要定位到相应的地方:

           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

     

    如果是XML里的值:

  •  

    Mapping时 不要带“@”


     

     

     


     

     

     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    posted on 2012-05-11 17:22  笨笨丁  阅读(1337)  评论(0编辑  收藏  举报