xsl的preceding::跟following::

案例是这样,因为现在架构是采用了mvc,即视图跟数据的提供模块分开,一个模块负责获取数据,而前台负责将数据按所需要的需求显示出来,现在我们是用java的来实现model的功能,即后台的数据操作,而前台的view,是采用xml + xsl来实现。因此,在设计时候的一个理念就是把数据按照一个个的VO在后台java填装好之后,用xml传给客户端,客户端接收到xml的数据的时候,就可以用xsl文件来对数据进行显示。

根据这种想法,当前台需要对数据进行统计,或分组时,我们将这种操作看成是一种特殊的视图显示,我们当然希望能在xsl里面完成。对于统计,xsl提供了sum跟count函数,实际使用没什么太大问题。

问题在于分组上面,xsl虽然提供了对node的分组,但当我们想知道,什么时候是分组的分界线的时候,即何时是分组开始,何时分组结束的时候,xsl并没有提供很好的支持。

一开始,我是用了xsl里面的following::跟preceding::再加上count,来计算之前的节点数跟之后的节点数,其中某个为零的时候,就可以判断此时是分组开始还是分组结束。可是,这时xsl的语法设计得并不好,xsl里面有个很常用的for-each的语句,可以用来进行对节点进行循环显示并对他们进行sorting,问题就出在for-each的sorting上,本来,xsl的这个sorting要给的印象是它已经把整个xml的数据全部重新sort了一遍,即顺序已经排好了。因为在for-each语句里面,它的节点确确实实是照着sort了之后的顺序走的。可是呢,当在for-each里面用了following::或者是preceding::时,就不是这样了,他并不认for-each sort了之后的顺序,而只是认xml里面各个node点排序的顺序。

就会造成这样的一个问题,当在for-each里面sort by两个以上的关键字,而认following和preceding的关键字少于sorting的关键字时。就会出现结果不一致的事情,为什么呢?因为显示的顺序跟数节点的两个顺序不一样,比如说,在xml里面有一组关键字一样的节点,在xml里面的顺序是abcd,但由于在for-each sorting的时候,因为加多了一个关键字,这组节点显示出来的顺序可能是cbda。ok,那会怎样呢,假设我们是看preceding来显示分组的标题吧。那么根据for-each sorting出来的结果,我们计出来的的preceding节点数是,c前面有2个,b前面有1个,d前面有3个,a前面为0个。而不是我们想要的0123,为什么?因为preceding看的还是用xml的node顺序来看的,即虽然显示的是cbda,但precding看还是看abcd来确定前面的节点数。这就会造成错误的结果。

对于这个,解决方法现在有两个,一个就是现在java里面sorting好了再出来,保证xml的节点顺序跟xsl sorting之后一样,就不会有问题,但这样做就背离了我们mvc的原则,即后台的数据处理不应该影响界面,而且这样修改起来很不好,因为实现同一功能的代码不应该写在两个地方。

再有一个就是不用count这个函数来计算当前或之后的节点数,直接把之前或之后的节点集传给for-each,即把preceding跟following当成一个distinct的功能,再一个个的显示出来,这样就避免了顺序不同的问题。可这种写法有点太过繁琐,特别是对于需要多次分组的情况,代码的写法要更复杂。

另外,对于preceding跟fowllowing的调用是非常消耗cpu资源的,特别是ms代码解析得也不是很好,对于四千多个节点,在for-each判断一次,将比一次I/O的时间还常,将近需要1分钟的时间,即是说,每次调用preceding跟fowllowing,系统都要整棵树走一下。确实不是很好的办法。

现在对于这种分组还没有更好的办法,瓶颈在于根本无法在xsl里面对变量重新赋值,如果可以就简单许多,现在尝试能否用template的方法来实现。

今天把template修改了一下,利用position来判断节点位置,然后判断是否应该进行分组,效率提高了很多,只用了原来三分之一的时间就可以完成。不过这种方法的缺点还是需要先在java里面sorting完再出来。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值