gpt4 book ai didi

xslt - 有没有一种技术可以将 XSL 转换管道组合成单个转换?

转载 作者:行者123 更新时间:2023-12-04 21:25:22 24 4
gpt4 key购买 nike

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

最佳答案

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

这是一个简单的例子 :

<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 文档时:
<doc/>

想要的结果 (第一遍添加元素 <one/> 作为顶部元素的子元素,然后第二遍添加另一个子元素 , immediately after the element ` 是在第一遍中创建的) 生产 :
<doc>
<one/>
<two/>
</doc>

FXSL中有一个非常合适的模板/函数这样做 : 这是 compose-flist 模板。它将初始数据参数和 N 个函数(模板)作为参数,并生成这些函数/模板的链式组合。

这是来自 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()扩展是必要的,任何链式转换都可以包含在一个真实的函数中。

关于xslt - 有没有一种技术可以将 XSL 转换管道组合成单个转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4237531/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com