Calling CMS Functions
XSLT's can call CMS Functions before, during or after execution.
The CMS Function system is what feeds your XSLT with data. Typically you define your function calls on the Functions tab in the XSLT Function editor - such functions run before your XSLT execute and the result XML is the input for the XSLT. This is convenient since you can preview the XML input and resulting XSLT output while you develop in the CMS Console.
You can also execute CMS Functions while or after your XSLT execute. In both cases you can use XSLT to define the CMS Function call markup and when executed dynamically during XSLT execution you can also have the running XSLT to parse the result.
Executing CMS Function calls after XSLT
It's fairly simple to execute CMS Functions after your XSLT has executed - you simply ensure that the CMS Function call markup is part of the XSLT output.
Here is a simple sample XSLT that output a function call that will print tomorrows date:
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml" exclude-result-prefixes="xsl f"> <xsl:template match="/"> <html> <head /> <body> <xsl:variable name="daystoadd" select="1" /> <function name="Composite.Utils.Date.AddDays" xmlns="http://www.composite.net/ns/function/1.0"> <param name="DaysToAdd" value="{$daystoadd}" /> </function> </body> </html> </xsl:template> </xsl:stylesheet>
You can see the 'dynamic' part by looking at the XSLT variable $daystoadd
- this will yield the following output:
<?xml version="1.0" encoding="utf-8"?> <html xmlns="http://www.w3.org/1999/xhtml"> <head/> <body> <f:function name="Composite.Utils.Date.AddDays" xmlns:f="http://www.composite.net/ns/function/1.0"> <f:param name="DaysToAdd" value="1"/> </f:function> </body> </html>
The C1 CMS rendering engine will locate all nested function calls and execute them and will continue to do so until no more function call markup is returned in function results. Note that you can introduce endless recursion this way.
Your XSLT can return multiple and nested <f:function />
elements - which is illustrated in the following pseudo XSLT:
<?xml version="1.0" encoding="utf-8"?> <f:function name="Shop.Presentation.ListMinimizer" xmlns:f="http://www.composite.net/ns/function/1.0"> <f:param name="Style" value="Compact" /> <f:param name="ItemRenderings"> <xsl:for-each select="$shoppingbasket/Product" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <f:function name="Shop.Presentation.ProductListItem"> <f:param name="ProductId" value="{@ProductId}" /> </f:function> </xsl:for-each> </f:param> </f:function>
Executing CMS Function calls during XSLT
You can execute CMS Function calls "runtime" - during the XSLT execution via an XSLT Extension. To execute a CMS Function dynamically, make the following changes to your XSLT:
- Include the following namespace declaration in your XSLT:
xmlns:c1="http://c1.composite.net/StandardFunctions"
- Write or locate a
<f:function />
call in your XSLT - Wrap a
<xsl:variable name="MyFunction" />
element around the function markup (see sample below) - When you need the result of the function call, execute
c1:CallFunction($MyFunction)
If the result is a node set (is XML) you can xsl:apply-templates
on it etc. like normal input XML. String, integer, date and Boolean values behave as normal.
The following pseudo XSLT shows a function call being dynamically constructed, then executed and the result (here a simple string) used:
<?xml version="1.0" encoding="utf-8"?> <xsl:template match="User" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:variable name="SendMailFunction"> <f:function name="Composite.Mail.SendMail" xmlns:f="http://www.composite.net/ns/function/1.0"> <f:param name="From" value="us@bazinga.com" /> <f:param name="To" value="{@EMail}" /> <f:param name="Subject" value="Hello {@Name}" /> <f:param name="IsHtml" value="false" /> <f:param name="Body">Hello there...</f:param> </f:function> </xsl:variable> <xsl:variable name="emailSentSuccessfully" select="c1:CallFunction($SendMailFunction)" xmlns:c1="http://c1.composite.net/StandardFunctions"/> <xsl:if test="$emailSentSuccessfully='false'"> Error sending mail... </xsl:if> </xsl:template>
In this example the CMS Function call is defined in the XSLT variable $SendMailFunction
- most of it is static markup, but the "To" and "Subject" parameters are built using XSLT. A small tip - use the "Insert | Function Markup" command to use a wizard to get the skeleton you need.
The variable $SendMailFunction
- containing the dynamically constructed function call - is passed to the XSLT extension method c1:CallFunction()
. The CMS Function is then executed and the return value is returned to XSLT. Most useful kinds of return types (.NET types) are XElement
, XhtmlDocument
, IEnumerable<XElement>
, string, int and bool - all this you can work with in XSLT.