Dynamic Sorting? or Sort by Parameter?
When you create a simple report that contains for example a single table, many users would like to have a single template that gets the column by which the table is sorted as a parameter - so that the end user can easily change it. Lately, I got this functionality working and thought I share it.First you will need to define a parameter:
<xsl:param name="order" select="'SALARY'" xdofo:ctx="begin"/>
Next you will create a table that is sorted for example by name This can be accomplished easily with the table wizard. The resulting for-each and sort statements are:
<?for-each:ROW?>
<sort:NAME;'ascending';data-type='text'?>
?
So in a first attempt we would replace NAME with $order to use the parameter to sort:
<?for-each:ROW?>
<?sort:$order;'ascending';data-type='text'?>
?
This does not work? Why? Well, $order contains a string,
while the <?sort:$order ?> statement which is translated into a
<xsl:sort select=?$order?/> expect a node as a parameter and not a name.
So how do we get the SALARY node from a variable that contains the text
鉄ALARY??
We can get the node by adding a predicate using the [] syntax. We first use the expression that matches any childnode: ./*. Now we add the condition that the name of the child node equals the content of the variable $order. The resulting expression is:
./*[name(.) = $order].
So we replace the NAME not with $order but with ./*[name(.) = $order] and achieve
<?for-each:ROW?>
<?sort:./*[name(.) = $order];'ascending';data-type='text'?>
?
This worked fine, with one caveat: The sort always sorts alphanumerical and not numerical ? meaning 1000 comes before 2. You will need to change the data-type to achieve correct sorting. You could achieve that with an if statement to set the data-type depending on the field name and run into some other issues ? or pass the type as a parameter.
If you want to use a parameter (e.g. with the name type) in for the data-type, you need to know that this field expects a string and not a node. If you write:
<?for-each:ROW?>
<?sort:./*[name(.) = $order];'ascending';data-type='$type'?>
?
your sorting will fail, because it will use the name of the variable $type as the data type and not its content. So you will need to user {} around the variable to substitute an XPATH expression or a variable inside the text. The final expression is:
<?for-each:ROW?>
<?sort:./*[name(.) = $order];'ascending';data-type='{$type}'?>
?
and your dynamic sorting should work like a charm? Unless you want to use an if statement to set the data-type depending on the parameter name ? but that again is a different story to be told at a different time.
KF







