f:apply implemented
Although the general concept was independently discovered, the finer details of this implementation are motivated by the excellent, comprehensive work of Dimitre Novatchev[0]. For those of us who either can't, or don't wish to, abaondon XSLT. [0]: http://conferences.idealliance.org/extreme/html/2006/Novatchev01/EML2006Novatchev01.htmlmaster
parent
061d4b7e09
commit
f50c2299fa
|
@ -0,0 +1,196 @@
|
||||||
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
|
<!--
|
||||||
|
Dynamic function application
|
||||||
|
|
||||||
|
Copyright (C) 2014 LoVullo Associates, Inc.
|
||||||
|
|
||||||
|
This file is part of hoxsl.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
This can be used to create higher-order functions.
|
||||||
|
|
||||||
|
If you need more arguments than this, then you may want to consider
|
||||||
|
another approach.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<stylesheet version="2.0"
|
||||||
|
xmlns="http://www.w3.org/1999/XSL/Transform"
|
||||||
|
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||||
|
xmlns:f="http://www.lovullo.com/xslink/apply">
|
||||||
|
|
||||||
|
|
||||||
|
<function name="f:apply">
|
||||||
|
<param name="fnref" as="element()" />
|
||||||
|
|
||||||
|
<apply-templates select="$fnref" mode="f:apply" />
|
||||||
|
</function>
|
||||||
|
|
||||||
|
|
||||||
|
<function name="f:apply">
|
||||||
|
<param name="fnref" as="element()" />
|
||||||
|
<param name="arg1" />
|
||||||
|
|
||||||
|
<apply-templates select="$fnref" mode="f:apply">
|
||||||
|
<with-param name="arg1" select="$arg1" />
|
||||||
|
</apply-templates>
|
||||||
|
</function>
|
||||||
|
|
||||||
|
|
||||||
|
<function name="f:apply">
|
||||||
|
<param name="fnref" as="element()" />
|
||||||
|
<param name="arg1" />
|
||||||
|
<param name="arg2" />
|
||||||
|
|
||||||
|
<apply-templates select="$fnref" mode="f:apply">
|
||||||
|
<with-param name="arg1" select="$arg1" />
|
||||||
|
<with-param name="arg2" select="$arg2" />
|
||||||
|
</apply-templates>
|
||||||
|
</function>
|
||||||
|
|
||||||
|
|
||||||
|
<function name="f:apply">
|
||||||
|
<param name="fnref" as="element()" />
|
||||||
|
<param name="arg1" />
|
||||||
|
<param name="arg2" />
|
||||||
|
<param name="arg3" />
|
||||||
|
|
||||||
|
<apply-templates select="$fnref" mode="f:apply">
|
||||||
|
<with-param name="arg1" select="$arg1" />
|
||||||
|
<with-param name="arg2" select="$arg2" />
|
||||||
|
<with-param name="arg3" select="$arg3" />
|
||||||
|
</apply-templates>
|
||||||
|
</function>
|
||||||
|
|
||||||
|
|
||||||
|
<function name="f:apply">
|
||||||
|
<param name="fnref" as="element()" />
|
||||||
|
<param name="arg1" />
|
||||||
|
<param name="arg2" />
|
||||||
|
<param name="arg3" />
|
||||||
|
<param name="arg4" />
|
||||||
|
|
||||||
|
<apply-templates select="$fnref" mode="f:apply">
|
||||||
|
<with-param name="arg1" select="$arg1" />
|
||||||
|
<with-param name="arg2" select="$arg2" />
|
||||||
|
<with-param name="arg3" select="$arg3" />
|
||||||
|
<with-param name="arg4" select="$arg4" />
|
||||||
|
</apply-templates>
|
||||||
|
</function>
|
||||||
|
|
||||||
|
|
||||||
|
<function name="f:apply">
|
||||||
|
<param name="fnref" as="element()" />
|
||||||
|
<param name="arg1" />
|
||||||
|
<param name="arg2" />
|
||||||
|
<param name="arg3" />
|
||||||
|
<param name="arg4" />
|
||||||
|
<param name="arg5" />
|
||||||
|
|
||||||
|
<apply-templates select="$fnref" mode="f:apply">
|
||||||
|
<with-param name="arg1" select="$arg1" />
|
||||||
|
<with-param name="arg2" select="$arg2" />
|
||||||
|
<with-param name="arg3" select="$arg3" />
|
||||||
|
<with-param name="arg4" select="$arg4" />
|
||||||
|
<with-param name="arg5" select="$arg5" />
|
||||||
|
</apply-templates>
|
||||||
|
</function>
|
||||||
|
|
||||||
|
|
||||||
|
<function name="f:apply">
|
||||||
|
<param name="fnref" as="element()" />
|
||||||
|
<param name="arg1" />
|
||||||
|
<param name="arg2" />
|
||||||
|
<param name="arg3" />
|
||||||
|
<param name="arg4" />
|
||||||
|
<param name="arg5" />
|
||||||
|
<param name="arg6" />
|
||||||
|
|
||||||
|
<apply-templates select="$fnref" mode="f:apply">
|
||||||
|
<with-param name="arg1" select="$arg1" />
|
||||||
|
<with-param name="arg2" select="$arg2" />
|
||||||
|
<with-param name="arg3" select="$arg3" />
|
||||||
|
<with-param name="arg4" select="$arg4" />
|
||||||
|
<with-param name="arg5" select="$arg5" />
|
||||||
|
<with-param name="arg6" select="$arg6" />
|
||||||
|
</apply-templates>
|
||||||
|
</function>
|
||||||
|
|
||||||
|
|
||||||
|
<function name="f:apply">
|
||||||
|
<param name="fnref" as="element()" />
|
||||||
|
<param name="arg1" />
|
||||||
|
<param name="arg2" />
|
||||||
|
<param name="arg3" />
|
||||||
|
<param name="arg4" />
|
||||||
|
<param name="arg5" />
|
||||||
|
<param name="arg6" />
|
||||||
|
<param name="arg7" />
|
||||||
|
|
||||||
|
<apply-templates select="$fnref" mode="f:apply">
|
||||||
|
<with-param name="arg1" select="$arg1" />
|
||||||
|
<with-param name="arg2" select="$arg2" />
|
||||||
|
<with-param name="arg3" select="$arg3" />
|
||||||
|
<with-param name="arg4" select="$arg4" />
|
||||||
|
<with-param name="arg5" select="$arg5" />
|
||||||
|
<with-param name="arg6" select="$arg6" />
|
||||||
|
<with-param name="arg7" select="$arg7" />
|
||||||
|
</apply-templates>
|
||||||
|
</function>
|
||||||
|
|
||||||
|
|
||||||
|
<function name="f:apply">
|
||||||
|
<param name="fnref" as="element()" />
|
||||||
|
<param name="arg1" />
|
||||||
|
<param name="arg2" />
|
||||||
|
<param name="arg3" />
|
||||||
|
<param name="arg4" />
|
||||||
|
<param name="arg5" />
|
||||||
|
<param name="arg6" />
|
||||||
|
<param name="arg7" />
|
||||||
|
<param name="arg8" />
|
||||||
|
|
||||||
|
<apply-templates select="$fnref" mode="f:apply">
|
||||||
|
<with-param name="arg1" select="$arg1" />
|
||||||
|
<with-param name="arg2" select="$arg2" />
|
||||||
|
<with-param name="arg3" select="$arg3" />
|
||||||
|
<with-param name="arg4" select="$arg4" />
|
||||||
|
<with-param name="arg5" select="$arg5" />
|
||||||
|
<with-param name="arg6" select="$arg6" />
|
||||||
|
<with-param name="arg7" select="$arg7" />
|
||||||
|
<with-param name="arg8" select="$arg8" />
|
||||||
|
</apply-templates>
|
||||||
|
</function>
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Abort processing on unknown function reference
|
||||||
|
|
||||||
|
This will occur if no application template is defined for the
|
||||||
|
given function reference. Override it if you wish to perform
|
||||||
|
autoloading or what have you.
|
||||||
|
|
||||||
|
If you generate the nullary and application template using
|
||||||
|
apply-gen, then you won't have to worry about this.
|
||||||
|
-->
|
||||||
|
<template mode="f:apply"
|
||||||
|
match="*"
|
||||||
|
priority="1">
|
||||||
|
<message terminate="yes">
|
||||||
|
<text>error: cannot apply unknown function reference: </text>
|
||||||
|
<copy-of select="." />
|
||||||
|
</message>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</stylesheet>
|
|
@ -0,0 +1,123 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Tests dynamic function application
|
||||||
|
|
||||||
|
Copyright (C) 2014 LoVullo Associates, Inc.
|
||||||
|
|
||||||
|
This file is part of hoxsl.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<stylesheet version="2.0"
|
||||||
|
xmlns="http://www.w3.org/1999/XSL/Transform"
|
||||||
|
xmlns:f="http://www.lovullo.com/xslink/apply"
|
||||||
|
xmlns:foo="http://www.lovullo.com/_junk">
|
||||||
|
|
||||||
|
<import href="../src/apply.xsl" />
|
||||||
|
|
||||||
|
|
||||||
|
<template mode="f:apply" match="foo:fn0">
|
||||||
|
<!-- return something to show that we were called properly -->
|
||||||
|
<sequence select="0" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<template mode="f:apply" match="foo:fn1">
|
||||||
|
<param name="arg1" />
|
||||||
|
|
||||||
|
<sequence select="string($arg1)" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<template mode="f:apply" match="foo:fn2">
|
||||||
|
<param name="arg1" />
|
||||||
|
<param name="arg2" />
|
||||||
|
|
||||||
|
<sequence select="concat($arg1, $arg2)" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<template mode="f:apply" match="foo:fn3">
|
||||||
|
<param name="arg1" />
|
||||||
|
<param name="arg2" />
|
||||||
|
<param name="arg3" />
|
||||||
|
|
||||||
|
<sequence select="concat($arg1, $arg2, $arg3)" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<template mode="f:apply" match="foo:fn4">
|
||||||
|
<param name="arg1" />
|
||||||
|
<param name="arg2" />
|
||||||
|
<param name="arg3" />
|
||||||
|
<param name="arg4" />
|
||||||
|
|
||||||
|
<sequence select="concat($arg1, $arg2, $arg3, $arg4)" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<template mode="f:apply" match="foo:fn5">
|
||||||
|
<param name="arg1" />
|
||||||
|
<param name="arg2" />
|
||||||
|
<param name="arg3" />
|
||||||
|
<param name="arg4" />
|
||||||
|
<param name="arg5" />
|
||||||
|
|
||||||
|
<sequence select="concat($arg1, $arg2, $arg3, $arg4,
|
||||||
|
$arg5)" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<template mode="f:apply" match="foo:fn6">
|
||||||
|
<param name="arg1" />
|
||||||
|
<param name="arg2" />
|
||||||
|
<param name="arg3" />
|
||||||
|
<param name="arg4" />
|
||||||
|
<param name="arg5" />
|
||||||
|
<param name="arg6" />
|
||||||
|
|
||||||
|
<sequence select="concat($arg1, $arg2, $arg3, $arg4,
|
||||||
|
$arg5, $arg6)" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<template mode="f:apply" match="foo:fn7">
|
||||||
|
<param name="arg1" />
|
||||||
|
<param name="arg2" />
|
||||||
|
<param name="arg3" />
|
||||||
|
<param name="arg4" />
|
||||||
|
<param name="arg5" />
|
||||||
|
<param name="arg6" />
|
||||||
|
<param name="arg7" />
|
||||||
|
|
||||||
|
<sequence select="concat($arg1, $arg2, $arg3, $arg4,
|
||||||
|
$arg5, $arg6, $arg7)" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<template mode="f:apply" match="foo:fn8">
|
||||||
|
<param name="arg1" />
|
||||||
|
<param name="arg2" />
|
||||||
|
<param name="arg3" />
|
||||||
|
<param name="arg4" />
|
||||||
|
<param name="arg5" />
|
||||||
|
<param name="arg6" />
|
||||||
|
<param name="arg7" />
|
||||||
|
<param name="arg8" />
|
||||||
|
|
||||||
|
<sequence select="concat($arg1, $arg2, $arg3, $arg4,
|
||||||
|
$arg5, $arg6, $arg7, $arg8)" />
|
||||||
|
</template>
|
||||||
|
</stylesheet>
|
|
@ -0,0 +1,175 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Tests dynamic function application
|
||||||
|
|
||||||
|
Copyright (C) 2014 LoVullo Associates, Inc.
|
||||||
|
|
||||||
|
This file is part of hoxsl.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<description xmlns="http://www.jenitennison.com/xslt/xspec"
|
||||||
|
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||||
|
xmlns:f="http://www.lovullo.com/xslink/apply"
|
||||||
|
xmlns:foo="http://www.lovullo.com/_junk"
|
||||||
|
stylesheet="apply-test.xsl">
|
||||||
|
|
||||||
|
<scenario label="f:apply">
|
||||||
|
<scenario label="applied to a function reference element">
|
||||||
|
<variable name="arg"
|
||||||
|
select="'foo'" />
|
||||||
|
|
||||||
|
<call function="f:apply">
|
||||||
|
<param name="fnref">
|
||||||
|
<foo:fn1 />
|
||||||
|
</param>
|
||||||
|
<param name="arg1" select="$arg" />
|
||||||
|
</call>
|
||||||
|
|
||||||
|
<!-- our test appliaction template simply echoes back its only
|
||||||
|
argument -->
|
||||||
|
<expect label="applies application template with mode f:apply"
|
||||||
|
test="$x:result = ($arg)" />
|
||||||
|
</scenario>
|
||||||
|
|
||||||
|
|
||||||
|
<scenario label="applying">
|
||||||
|
<scenario label="nullary function">
|
||||||
|
<call function="f:apply">
|
||||||
|
<param name="fnref"><foo:fn0 /></param>
|
||||||
|
</call>
|
||||||
|
|
||||||
|
<expect label="passes each argument"
|
||||||
|
test="$x:result = 0" />
|
||||||
|
</scenario>
|
||||||
|
|
||||||
|
|
||||||
|
<scenario label="unary function">
|
||||||
|
<call function="f:apply">
|
||||||
|
<param name="fnref"><foo:fn1 /></param>
|
||||||
|
<param name="arg1" select="1" />
|
||||||
|
</call>
|
||||||
|
|
||||||
|
<expect label="passes each argument"
|
||||||
|
test="$x:result = '1'" />
|
||||||
|
</scenario>
|
||||||
|
|
||||||
|
|
||||||
|
<scenario label="binary function">
|
||||||
|
<call function="f:apply">
|
||||||
|
<param name="fnref"><foo:fn2 /></param>
|
||||||
|
<param name="arg1" select="1" />
|
||||||
|
<param name="arg2" select="2" />
|
||||||
|
</call>
|
||||||
|
|
||||||
|
<expect label="passes each argument"
|
||||||
|
test="$x:result = '12'" />
|
||||||
|
</scenario>
|
||||||
|
|
||||||
|
|
||||||
|
<scenario label="ternary function">
|
||||||
|
<call function="f:apply">
|
||||||
|
<param name="fnref"><foo:fn3 /></param>
|
||||||
|
<param name="arg1" select="1" />
|
||||||
|
<param name="arg2" select="2" />
|
||||||
|
<param name="arg3" select="3" />
|
||||||
|
</call>
|
||||||
|
|
||||||
|
<expect label="passes each argument"
|
||||||
|
test="$x:result = '123'" />
|
||||||
|
</scenario>
|
||||||
|
|
||||||
|
|
||||||
|
<scenario label="4-ary function">
|
||||||
|
<call function="f:apply">
|
||||||
|
<param name="fnref"><foo:fn4 /></param>
|
||||||
|
<param name="arg1" select="1" />
|
||||||
|
<param name="arg2" select="2" />
|
||||||
|
<param name="arg3" select="3" />
|
||||||
|
<param name="arg4" select="4" />
|
||||||
|
</call>
|
||||||
|
|
||||||
|
<expect label="passes each argument"
|
||||||
|
test="$x:result = '1234'" />
|
||||||
|
</scenario>
|
||||||
|
|
||||||
|
|
||||||
|
<scenario label="5-ary function">
|
||||||
|
<call function="f:apply">
|
||||||
|
<param name="fnref"><foo:fn5 /></param>
|
||||||
|
<param name="arg1" select="1" />
|
||||||
|
<param name="arg2" select="2" />
|
||||||
|
<param name="arg3" select="3" />
|
||||||
|
<param name="arg4" select="4" />
|
||||||
|
<param name="arg5" select="5" />
|
||||||
|
</call>
|
||||||
|
|
||||||
|
<expect label="passes each argument"
|
||||||
|
test="$x:result = '12345'" />
|
||||||
|
</scenario>
|
||||||
|
|
||||||
|
|
||||||
|
<scenario label="6-ary function">
|
||||||
|
<call function="f:apply">
|
||||||
|
<param name="fnref"><foo:fn6 /></param>
|
||||||
|
<param name="arg1" select="1" />
|
||||||
|
<param name="arg2" select="2" />
|
||||||
|
<param name="arg3" select="3" />
|
||||||
|
<param name="arg4" select="4" />
|
||||||
|
<param name="arg5" select="5" />
|
||||||
|
<param name="arg6" select="6" />
|
||||||
|
</call>
|
||||||
|
|
||||||
|
<expect label="passes each argument"
|
||||||
|
test="$x:result = '123456'" />
|
||||||
|
</scenario>
|
||||||
|
|
||||||
|
|
||||||
|
<scenario label="7-ary function">
|
||||||
|
<call function="f:apply">
|
||||||
|
<param name="fnref"><foo:fn7 /></param>
|
||||||
|
<param name="arg1" select="1" />
|
||||||
|
<param name="arg2" select="2" />
|
||||||
|
<param name="arg3" select="3" />
|
||||||
|
<param name="arg4" select="4" />
|
||||||
|
<param name="arg5" select="5" />
|
||||||
|
<param name="arg6" select="6" />
|
||||||
|
<param name="arg7" select="7" />
|
||||||
|
</call>
|
||||||
|
|
||||||
|
<expect label="passes each argument"
|
||||||
|
test="$x:result = '1234567'" />
|
||||||
|
</scenario>
|
||||||
|
|
||||||
|
|
||||||
|
<scenario label="8-ary function">
|
||||||
|
<call function="f:apply">
|
||||||
|
<param name="fnref"><foo:fn8 /></param>
|
||||||
|
<param name="arg1" select="1" />
|
||||||
|
<param name="arg2" select="2" />
|
||||||
|
<param name="arg3" select="3" />
|
||||||
|
<param name="arg4" select="4" />
|
||||||
|
<param name="arg5" select="5" />
|
||||||
|
<param name="arg6" select="6" />
|
||||||
|
<param name="arg7" select="7" />
|
||||||
|
<param name="arg8" select="8" />
|
||||||
|
</call>
|
||||||
|
|
||||||
|
<expect label="passes each argument"
|
||||||
|
test="$x:result = '12345678'" />
|
||||||
|
</scenario>
|
||||||
|
</scenario>
|
||||||
|
</scenario>
|
||||||
|
</description>
|
Loading…
Reference in New Issue