第二天(8/12/2009),下午
关键词:管道,流处理,XSLT 2.1,推与挽模型(Push and Pull Model)
在我的书架上有两本非常醒目的红色封面参考书,XSLT 2.0[1]和XPath 2.0[2],这两本书的作者Michael Kay的讲演内容就是今天下午我想着重向大家介绍的。
会议安排了Michael连续两个主题讲演。第一个是关于“基于管道的XML处理”(Pipeline based XML processing)[3],第二个是“制定中的XSLT 2.1标准的流处理功能”。基于管道的XML处理所指的是在对XML的处理过程中需要经过一系列的步骤,而这些步骤实际上可以通过管道(pipeline)采用流的方式处理,当然前提是这个处理的每个步骤都需要支持“流”(streamability,这个英文单词是XSLT标准制定工作组自创的)。而所谓基于“流”的处理是指一个相对内存来说巨大的XML文件可以被分割成比较小的单元进行顺序处理。而这样的单元可以是每一个SAX [4]的消息,例如startElement和EndElement,或者是一个XML的部分,比如一个节点(Node)和原子化的量值(Atomic Value)。
而对于XML的处理来说,一般只有两种方式:组构和析构(compose and decompose)。每个步骤则采用“推”或“挽”的方式对XML组构或析构。在将这些步骤连接起来的时候由于它们各自的极化方式不一样(“推”或“挽”)或对XML的单元访问方式不一样(顺序,乱序,或在一个子树中乱序,子树与子树间顺序),要么需要一个控制器(controller)将“推”模型和“挽”模型连接起来,要么需要将XML的子树或全树缓存在内存中,结果往往造成整个处理流程的效率降低。Michael举了一个他自己的XQuery处理器例子,由于使用控制器和两个线程将“推”和“挽”两个步骤联系起来,结果比起一个单一“推”或单一“挽”的处理流程效率降低了差不多45%。会后有人提问有关在多核的系统中,是否这样的架构会体现出优势,Michael表示肯定。另外,他介绍了一个非常有用但被人淡忘的概念[5],其实所谓的“推”或“挽”模型是可以相互转换的,在多线程的代价比较大的环境里,使用“协同程序”(co-routine)的方法可以在单一线程的条件下将“挽”模型转变为“推”模型,反之亦然。
XSLT 2.1的流处理功能是Michael应邀添加的新讲座,类似在音乐会里的加演节目。作为XSLT标准的编辑(editor),Michael对于这方面的内容当然非常熟悉。由于这篇博客的长度有限,我无法深入介绍XSLT 2.1的流处理功能,况且许多标准的细节还在起草阶段,这里就一些有趣或有争议的功能稍作解读:
XSLT 2.1还引入了xsl:mode语句,它同xsl:template的“mode”属性一起用来标识某个XSL的模板是否适用于“流”处理;引入了xsl:merge语句支持多个XML文件的相互融合,这里就不一一细数了。希望了解更多XSLT最新情况的读者可以关注一下XSL标准的官方网站[6]。