有没有一种技术可以将XSL转换的流水线组合成单个转换? [英] Is there a technique to combine a pipeline of XSL transformations into a single transformation?

查看:86
本文介绍了有没有一种技术可以将XSL转换的流水线组合成单个转换?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经编写了一个使用15个XSL样式表的管道的应用程序,并且我开始着手调整其性能.它设计为可移植的,因此可以在Web浏览器环境和桌面中运行.在桌面上,我认为将样式表分隔开作为多个转换的管道可能是有意义的,因为这允许每个单独的转换在其自己的线程中运行,这在具有多核的CPU上非常有效.但是,不仅浏览器环境是单线程的,而且在大多数浏览器中,暴露给JavaScript的XSL处理API要求将每个单独转换的结果解析回DOM对象,这似乎效率很低.我认为,如果可能的话,在浏览器环境中运行时将所有样式表组合为一个样式表将是有利的.我对如何使用exsl:node-set(大多数浏览器支持)如何实现这一想法有所了解,但是我不清楚我想象中的技术是否可以推广.是否存在将XSL样式表的管道转换为单个XSL样式表的通用技术,从而保留完整管道的语义?自动化的解决方案将是理想的选择.

I have written an application which uses a pipeline of 15 XSL stylesheets, and I'm beginning to work on tuning its performance. It's designed to be portable, so that it can be run in both the web browser environment, and on the desktop. On the desktop, I think it may make sense to keep the stylesheets separated out as a pipeline of multiple transformations, as this allows each individual transformation to be run in its own thread, which can be very efficient on CPUs with multiple cores. However, not only is the browser environment is single-threaded, in most browsers, the XSL processing API exposed to JavaScript requires parsing the result of each individual transformation back into a DOM object, which seems inefficient. I think it would therefore be advantageous to combine all of the stylesheets into a single stylesheet when running in the context of the browser environment, if that is possible. I have an idea of how this may be accomplished with exsl:node-set (which most browsers support), but it's not clear to me if the technique I'm imagining is generalizable. Is there a general technique for transforming a pipeline of XSL stylesheets into a single XSL stylesheet, such that the semantics of the complete pipeline are preserved? An automated solution would be ideal.

推荐答案

有一种技术,它允许将独立的转换链接在一起,其中第k个转换的输出是第(k + 1)个变换.

There is a technique that allows independent transformations to be chained together where the output of the k-th transformation is the input of the (k+1)-th transformation.

这是一个简单的示例:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ext="http://exslt.org/common"
    exclude-result-prefixes="ext xsl">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="node()|@*" name="identity">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="/">
  <xsl:variable name="vrtfPass1">
   <xsl:apply-templates select="node()"/>
  </xsl:variable>

  <xsl:apply-templates mode="pass2"
   select="ext:node-set($vrtfPass1)/node()"/>
 </xsl:template>

 <xsl:template match="/*">
     <xsl:copy>
       <xsl:copy-of select="@*"/>
       <one/>
     <xsl:apply-templates/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="node()|@*" mode="pass2">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*" mode="pass2"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="/*/one" mode="pass2" >
     <xsl:call-template name="identity"/>
      <two/>
 </xsl:template>
</xsl:stylesheet>

在以下XML文档上应用此转换时:

when this transformation is applied on the following XML document:

<doc/>

所需结果(第一遍将元素<one/>添加为顶级元素的子元素,然后第二遍添加在第一遍中创建的另一个子元素, immediately after the element`. )已产生:

the wanted result (the first pass addds the element <one/> as a child of the top element, then the second pass adds another child, , immediately after the element` that was created in the first pass) is produced:

<doc>
   <one/>
   <two/>
</doc>

FXSL 中有一个非常合适的模板/功能可以做到这一点:是

There is a very suitable template/function in FXSL to do this: this is the compose-flist template. It takes as parameters an initial data argument and N functions (templates) and produces the chained composition of these functions/templates.

这是FXSL库中的测试示例:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="http://fxsl.sf.net/"
xmlns:myFun1="f:myFun1"
xmlns:myFun2="f:myFun2" 
xmlns:ext="http://exslt.org/common"
exclude-result-prefixes="xsl f ext myFun1 myFun2"
>
  <xsl:import href="compose.xsl"/>
  <xsl:import href="compose-flist.xsl"/>

  <!-- to be applied on any xml source -->

  <xsl:output method="text"/>
  <myFun1:myFun1/>
  <myFun2:myFun2/>


  <xsl:template match="/">

    <xsl:variable name="vFun1" select="document('')/*/myFun1:*[1]"/>
    <xsl:variable name="vFun2" select="document('')/*/myFun2:*[1]"/>
    Compose:
    (*3).(*2) 3 = 
    <xsl:call-template name="compose">
      <xsl:with-param name="pFun1" select="$vFun1"/>
      <xsl:with-param name="pFun2" select="$vFun2"/>
      <xsl:with-param name="pArg1" select="3"/>
    </xsl:call-template>

    <xsl:variable name="vrtfParam">
      <xsl:copy-of select="$vFun1"/>
      <xsl:copy-of select="$vFun2"/>
      <xsl:copy-of select="$vFun1"/>
    </xsl:variable>

    Multi Compose:
    (*3).(*2).(*3) 2 = 
    <xsl:call-template name="compose-flist">
      <xsl:with-param name="pFunList" select="ext:node-set($vrtfParam)/*"/>
      <xsl:with-param name="pArg1" select="2"/>
    </xsl:call-template>
  </xsl:template>

  <xsl:template match="myFun1:*" mode="f:FXSL">
    <xsl:param name="pArg1"/>

    <xsl:value-of select="3 * $pArg1"/>
  </xsl:template>

  <xsl:template match="myFun2:*" mode="f:FXSL">
    <xsl:param name="pArg1"/>

    <xsl:value-of select="2 * $pArg1"/>
  </xsl:template>
</xsl:stylesheet>

将此转换应用于任何xml文档(未使用)时,会产生所需的正确结果:

Compose:
(*3).(*2) 3 = 
18

Multi Compose:
(*3).(*2).(*3) 2 = 
36

请注意:在XSLT 2.0及更高版本中,不需要xxx:node-set()扩展,并且任何链式转换都可以包含在实际函数中.

Do note: In XSLT 2.0 and later no xxx:node-set() extension is necessary, and any of the chained transformations can be contained in a real function.

这篇关于有没有一种技术可以将XSL转换的流水线组合成单个转换?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆