I have an XSLT 2.0 stylesheet. I need to perform a for-each-group loop, but the value I am grouping on may change, based on parameters passed into the stylesheet.
For example, if my XML looks like this (simplified for this example):
<root><row><date>2001-01-01</date><text>abc</text></row><row><date>2003-04-02</date><text>xyz</text></row>...</root>
I want to perform a for-each-group, grouping on a function applied to the date node. for example, it might be this:
<xsl:for-each-group select="/root/row" group-by="substring(date,1,4)">
or this:
<xsl:for-each-group select="/root/row" group-by="substring(date,1,7)">
I might even need to group on a different node, like . So I could use:
<xsl:for-each-group select="/root/row" group-by="$variable">
Is there any way to define a variable with the function and node I want to group on and then use that variable in the group-by expression? or some other way to do this? I tried using a simple variable, but that did not work, both (the second is inside single quotes):
<xsl:variable name="variable" select="substring(date,1,4)"/>
and
<xsl:variable name="variable" select="'substring(date,1,4)'"/>
I have a related question, but it likely has the same answer. I also need to perform an where the select will also need to use this same variable, like:
<xsl:value-of select="/root/row/$variable"/>
Thanks!
The real need here is for higher order functions: if the variable $f is bound to a function that computes the grouping key, then you can do group-by="$f(.)". This needs XSLT 3.0. However, it can be simulated in XSLT 2.0 using Dimitre Novatchev's FXSL library. I haven't used this with Saxon-CE, but apart from the fact that it's probably a bit big, there's no reason in principle why it shouldn't work.
You can use
substring(*[local-name() = $var1], 1, $var2)
where you then bindvar1
as'date'
and the other variable with a number value.The short answer to your question is no. A variable holds the result of evaluating an expression, not the expression itself. Moreover, you cannot pass an expression as such in parameter - you are only passing a string.
While you can dance around the issue to some extent as shown by Martin Honnen in his answer, you should really find out if your processor supports some kind of evaluate() extension function, such as: http://www.saxonica.com/documentation/#!functions/saxon/evaluate for example.