在XSLT中,是否可以有一个指向函数的指针?

时间:2016-10-05 17:31:07

标签: xml xslt

示例:

<xsl:function name="my:function" as="xs:integer">
    <xsl:param name="pNum" as="xs:integer" />
    <xsl:sequence select="$pNum * 2" />
</xsl:function>

<xsl:sequence select="my:function(1)" />

我希望能够调用my:function,如果可能,请保留对此函数的引用。

下面的代码不能工作,但是想表明我想要做的事情:

<xsl:variable name="vFn" select="my:function" />
<xsl:sequence select="$vFn(5)" />

我正在对明文格式的纯文本文件进行转换,将其转换为html。我不确定它是否使我在xml文档上运行的事情变得复杂。

3 个答案:

答案 0 :(得分:4)

对于来到这里的其他人可能感兴趣:Dimitre Novatchev设计了一种在XSLT 2.0中工作的方法(或者如果用命名模板代替函数,即使在1.0中,也使用节点集扩展)。 (他还创建了一个名为FXSL的库,利用该技术)。

创建一个包含以函数命名的元素的变量:

<xsl:variable name="my:function" as="element()">
  <my:function/>
</xsl:variable>

然后创建一个匹配此元素的模板规则并调用函数:

<xsl:template mode="dyn" match="my:function">
  <xsl:param name="p1"/>
  <xsl:sequence select="my:function($p1)"/>
</xsl:template>

现在定义一个动态调用函数:

<xsl:function name="dyn:call">
  <xsl:param name="function"/>
  <xsl:param name="param"/>
  <xsl:apply-templates select="$function" mode="dyn">
    <xsl:with-param name="p1" select="$param"/>
  </xsl:apply-templates>
</xsl:function>

现在您可以使用变量$my:function作为函数的代理,将其作为

调用
 ... select="dyn:call($my:function, 2)"/>

答案 1 :(得分:2)

可以在使用<xsl:variable name="vFn" select="my:function#1"/>的XSLT 3.0中查看https://www.w3.org/TR/xpath-30/#id-dynamic-function-invocationhttps://www.w3.org/TR/xpath-30/#id-named-function-ref

答案 2 :(得分:2)

<强>予。这是一个XSLT 1.0示例,我在FXSL中使用的技术:

<xsl:stylesheet version = "1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:f1="8B9C63F4-F4AB5D11-994A0001-B4CD626F"
  xmlns:f2="AB02AC1C-1C65B3FF-77C5FFFE-4B329DA1" >
  <f1:f1/>
  <f2:f2/>

  <xsl:variable name = "vFun1" select = "document('')/*/f1:*[1]" />
  <xsl:variable name = "vFun2" select = "document('')/*/f2:*[1]" />

  <xsl:template match="f1:*">
      <xsl:param name = "pX" />
      <xsl:value-of select = "2 * $pX" />
  </xsl:template>

  <xsl:template match="f2:*">
      <xsl:param name = "pX" />
      <xsl:value-of select = "3 * $pX" />
  </xsl:template>

  <xsl:template match = "/">
    <xsl:call-template name = "mySum" >
      <xsl:with-param name = "pX" select = "3" />
      <xsl:with-param name = "pFun1" select = "$vFun1" />
      <xsl:with-param name = "pFun2" select = "$vFun2" />
    </xsl:call-template>
  </xsl:template>

  <xsl:template name = "mySum" >
    <xsl:param name = "pX" />
    <xsl:param name = "pFun1" select = "/.." />
    <xsl:param name = "pFun2" select = "/.." />

    <xsl:variable name = "vFx_1" >
      <xsl:apply-templates select = "$pFun1" >
        <xsl:with-param name = "pX" select = "$pX" />
      </xsl:apply-templates>
    </xsl:variable>

    <xsl:variable name = "vFx_2" >
      <xsl:apply-templates select = "$pFun2" >
        <xsl:with-param name = "pX" select = "$pX" />
      </xsl:apply-templates>
    </xsl:variable>

    <xsl:value-of select = "$vFx_1 + $vFx_2" />
  </xsl:template>
</xsl:stylesheet>

名为mySum的模板传递两个参数,即一个参数的“函数指针”,以及该单个参数的值。

它调用每个动态传递的函数,并生成结果的总和。

如上所述,这两个函数是:1)double(x)和2)triple(x)

因此,结果必须为:double(x) + triple(x)5*x

事实上,结果是15,即5 * 3。这里的转换应用于任何XML文档 - 例如<t/> - 实际上没有使用它。

建议您修改这两个功能,并在每次产生正确结果时查看。

<强> II。 XSLT 2.0实施:

正如你所看到的,这里的调用实际上传递了两个函数:

f:applyAndSum(f:funTwice(), f:funFiveTimes(), 3)



<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:f="http://fxsl.sf.net/" exclude-result-prefixes="f">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <xsl:function name="f:apply">
   <xsl:param name="pFunc" as="element()"/>
   <xsl:param name="arg1"/>

   <xsl:apply-templates select="$pFunc" mode="f:FXSL">
      <xsl:with-param name="arg1" select="$arg1"/>
   </xsl:apply-templates>
  </xsl:function>

  <xsl:function name="f:apply">
   <xsl:param name="pFunc" as="element()"/>
   <xsl:param name="arg1"/>
   <xsl:param name="arg2"/>

   <xsl:apply-templates select="$pFunc" mode="f:FXSL">
      <xsl:with-param name="arg1" select="$arg1"/>
      <xsl:with-param name="arg2" select="$arg2"/>
   </xsl:apply-templates>
 </xsl:function>

  <xsl:template match="/">
    <xsl:sequence select=
      "f:applyAndSum(f:funTwice(), f:funFiveTimes(), 3)"/>
  </xsl:template>

  <xsl:function name="f:applyAndSum">
    <xsl:param name="arg1" as="element()"/>
    <xsl:param name="arg2" as="element()"/>
    <xsl:param name="arg3"/>

    <xsl:sequence select=
      "f:apply($arg1,$arg3) + f:apply($arg2,$arg3)"/>
  </xsl:function>

  <xsl:function name="f:funTwice" as="element()">
     <f:funTwice/>
  </xsl:function>

  <xsl:function name="f:funFiveTimes" as="element()">
     <f:funFiveTimes/>
  </xsl:function>

  <xsl:template match="f:funTwice" mode="f:FXSL">
     <xsl:param name="arg1"/>

     <xsl:sequence select ="f:funTwice($arg1)"/>
  </xsl:template>

  <xsl:template match="f:funFiveTimes" mode="f:FXSL">
     <xsl:param name="arg1"/>

     <xsl:sequence select ="f:funFiveTimes($arg1)"/>
  </xsl:template>

  <xsl:function name="f:funTwice">
     <xsl:param name="arg1"/>

     <xsl:sequence select="2*$arg1"/>
  </xsl:function>

  <xsl:function name="f:funFiveTimes">
     <xsl:param name="arg1"/>

     <xsl:sequence select="5*$arg1"/>
  </xsl:function>
</xsl:stylesheet>

这里有两个链接可以更系统地介绍FXSL:

  1. original FXSL page - 这只是XSLT 1.0,

  2. A paper about FXSL 2 - FXSL for XSLT 2.0