embeding od condition in xsl when getting error - xslt

below is the xsl tag on which I am getting the error as i have used xsl:when intead of xsl:if , folks please advise how can I re correct it so that i do not get compilation exception while transforming the xsl again I am using xslt 1.0
<xsl:when test="abcid=dec_id">
<xsl:for-each select="$qq_Obj/ert_Period/ytr_Period">
<xsl:variable name="ABC_Rate">
<xsl:value-of select="$Sds/oht_Period/rew_Period/#vgRate" />
</xsl:variable>
<xsl:choose>
<xsl:when test="$iue_first=#vgRate">
<xsl:value-of select="'AAA'" />
</xsl:when>
<xsl:value-of select="'BBB'" />
</xsl:choose>
</xsl:for-each>
</xsl:when>

You need to enclose the "else" part of an xsl:choose in an xsl:otherwise:
<xsl:choose>
<xsl:when test="$iue_first=#vgRate">
<xsl:value-of select="'AAA'" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'BBB'" />
</xsl:otherwise>
</xsl:choose>

Related

Implement dynamic xpath in XSLT: for-each-group

I am trying to use saxon:evaluate to reduce repeated code in an xsl function.
However anything I try returns an error.
This is a section of the repetitive code.
<!--Select by outputclass and group by attribute-->
<xsl:when test="$from='oclass-attribute'">
<xsl:for-each-group select="$compose//*[contains(#outputclass,$sel)]" group-by="#*[name()=$group]">
<xsl:sort select="current-grouping-key()" />
<element key="{current-grouping-key()}">
<xsl:if test="number(current-group()[1])=number(current-group()[1])">
<xsl:attribute name="max" select="max(current-group())"/>
<xsl:attribute name="sum" select="sum(current-group())"/>
</xsl:if>
<xsl:copy-of select="current-group()[1]"/>
</element>
</xsl:for-each-group>
</xsl:when>
<!--Select by node and group by child node-->
<xsl:when test="$from='node-childnode'">
<xsl:for-each-group select="$compose//*[name()=$sel]" group-by="child::*[name()=$group]">
<xsl:sort select="current-grouping-key()" />
<element key="{current-grouping-key()}">
<xsl:if test="number(current-group()[1])=number(current-group()[1])">
<xsl:attribute name="max" select="max(current-group())"/>
<xsl:attribute name="sum" select="sum(current-group())"/>
</xsl:if>
<xsl:copy-of select="current-group()[1]"/>
</element>
</xsl:for-each-group>
</xsl:when>
What I want is to pass a parameter dictating whether it is an element-name or outputclass-attribute that is selected.
Then another parameter dictating what to group by: attribute or parent, child, following or preceding node.
What I have tried is below:
<xsl:variable name="oSel">
<xsl:choose>
<xsl:when test="starts-with($from,'oclass-')">
<xsl:value-of select="$compose//*[contains(#outputclass,$sel)]"/>
</xsl:when>
<xsl:when test="starts-with($from,'node-')">
<xsl:value-of select="$compose//*[name()=$sel]"/>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:variable>
<xsl:variable name="oGroup">
<xsl:choose>
<xsl:when test="ends-with($from,'-attribute')">
<xsl:value-of select="*/#*[local-name()=$group]"/>
</xsl:when>
<xsl:when test="ends-with($from,'-childnode')">
<xsl:value-of select="*/*[name()=$group]"/>
</xsl:when>
<xsl:when test="ends-with($from,'-parentnode')">
<xsl:value-of select="parent::*[name()=$group]"/>
</xsl:when>
<xsl:when test="ends-with($from,'-followingnode')">
<xsl:value-of select="following-sibling::*[name()=$group][1]"/>
</xsl:when>
<xsl:when test="ends-with($from,'-precedingnode')">
<xsl:value-of select="preceding-sibling::*[name()=$group][1]"/>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:variable>
<xsl:variable name="test">
<!--<xsl:for-each-group select="saxon:evaluate($oSel)" group-by="saxon:evaluate($oGroup)">-->
<xsl:for-each-group select="saxon:evaluate($oSel)" group-by="saxon:evaluate($oGroup)">
<element key="{current-grouping-key()}">
<xsl:if test="number(current-group()[1])=number(current-group()[1])">
<xsl:attribute name="max" select="max(current-group())"/>
<xsl:attribute name="sum" select="sum(current-group())"/>
</xsl:if>
<xsl:copy-of select="current-group()[1]"/>
</element>
</xsl:for-each-group>
</xsl:variable>
I have looked into the saxon documentation and tried all sorts of solutions but none of them are working. Is it possible to do this?
Should have added that I am using Saxon 9.1.0.8 - Sorry, still new to XSLT
Firstly, saxon:evaluate() isn't the right tool for the job.
Now, why isn't it working? To declare the value of $oSel, you've done something like this:
<xsl:value-of select="$compose//*[contains(#outputclass,$sel)]"/>
which evaluates the expression in the select attribute and returns its result. But you're then passing $oSel to saxon:evaluate(), which expects a string containing an XPath expression. I think you're trying to bind the variable to the expression "$compose//*[contains(#outputclass,$sel)]", not to the result of evaluating this expression. To do that you would have to write
<xsl:value-of select="'$compose//*[contains(#outputclass,$sel)]'"/>
Note the extra quotes; but that would now fail because the expression passed to saxon:evaluate() can't explicitly use variables such as $compose (there's a mechanism to pass parameters, but you don't really want to go there).
In XSLT 3.0 saxon:evaluate is superseded by the standard instruction xsl:evaluate; but you don't want that one either.
The right mechanism to be using here is higher order functions.
In XSLT 3.0 you can write
<xsl:for-each-group select="$compose//*[$predicate(.)]" group-by="$grouping-key(.)">
Where $predicate and $grouping-key are variables bound to user-defined functions. You can bind these variables with logic like this:
<xsl:variable name="predicate" as="function(element()) as xs:boolean">
<xsl:choose>
<xsl:when test="starts-with($from,'oclass-')">
<xsl:sequence select="function($n){contains($n/#outputclass,$sel)}"/>
</xsl:when>
<xsl:when test="starts-with($from,'node-')">
<xsl:sequence select="function($n){name($n)=$sel}"/>
</xsl:when>
</xsl:choose>
</xsl:variable>
Change the xpath as below.
$compose//*[name()=$sel or contains(#outputclass,$sel)]
Here is the final code looks like
<xsl:when test="$from='oclass-attribute'">
<xsl:for-each-group select="$compose//*[name()=$sel or contains(#outputclass,$sel)]" group-by="#*[name()=$group]">
<xsl:sort select="current-grouping-key()" />
<element key="{current-grouping-key()}">
<xsl:if test="number(current-group()[1])=number(current-group()[1])">
<xsl:attribute name="max" select="max(current-group())"/>
<xsl:attribute name="sum" select="sum(current-group())"/>
</xsl:if>
<xsl:copy-of select="current-group()[1]"/>
</element>
</xsl:for-each-group>
Try
select="if ($from='oclass-attribute') then $compose//*[contains(#outputclass,$sel)] else $compose//*[name()=$sel]"
and use the same approach for the group-by attribute:
group-by="if ($from='oclass-attribute') then #*[name()=$group] else child::*[name()=$group]"

incorporating string into the when contidtion in xsl

I am trying to incorporate string into the when condition, but it does not work.
I have tried this:
<xsl:text>Salary:</xsl:text>
<xsl:for-each select="z:SalaryRecord">
<xsl:choose>
<xsl:when test="z:SalaryRecord = 'agreement'">
<xsl:value-of select="concat(' ',position(),' ',z:Type,'
')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat(' ',position(),' ',' ',z:Type,'(','from ',z:AmountFrom, ' to ',z:AmountTo,')','
')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
and this:
<xsl:when test="z:SalaryRecord::text() = 'agreement'">
and this
<xsl:when test="z:SalaryRecord == 'agreement'">
My XML source code:
<RequiredSalary>
<SalaryRecord>
<Type>monthly</Type>
<AmountFrom>1000</AmountFrom>
<AmountTo>2000</AmountTo>
</SalaryRecord>
<SalaryRecord>
<Type>agreement</Type>
</SalaryRecord>
</RequiredSalary>
Any idea pls?
thanks
One fix to your situation may be the following template. However, you'd have to define a namespace for the z prefix in your stylesheet. Try adding xmlns:z="http://whatever.is.your.namespace" to your XSLT stylesheet element.
<xsl:template match="z:RequiredSalary">
<xsl:for-each select="z:SalaryRecord">
<xsl:text>Salary:</xsl:text>
<xsl:choose>
<xsl:when test="z:Type = 'agreement'">
<xsl:value-of select="concat(' ',position(),' ',z:Type,'
')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat(' ',position(),' ',' ',z:Type,'(','from ',z:AmountFrom, ' to ',z:AmountTo,')','
')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<xsl:value-of select="'
'" />
</xsl:template>

how to remove hyphen from string +xslt

how to remove hyphen from string like "19650512-0065" to "196505120065"
using this template : passing theID =
<xsl:template name="unformatLFPartyID">
<xsl:param name="theID" select="." />
<xsl:variable name="idSuffix" select="string-length($theID) - 3" />
<xsl:choose>
<xsl:when test="contains($theID,'-')">
<xsl:value-of select="substring($theID,0,$idSuffix)" />
<xsl:value-of select="substring($theID, $idSuffix)" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$theID" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Try replacing the xsl:variable and entire xsl:choose with:
<xsl:value-of select="translate($theID,'-','')"/>

putting the xsl condition in a better way

Please advise is there any better way to express this below xsl condition or this below one is correct.. we are using xslt 1.0
<xsl:if test="$abcPeriod_first=gfd_Rate">
<xsl:value-of select="'AAA'" />
</xsl:if>
<xsl:value-of select="'BBB'" />
If you want an if...else then I believe your current condition is not sufficient. You could use the following:
<xsl:choose>
<xsl:when test="$abcPeriod_first=gfd_Rate">
<xsl:value-of select="'AAA'" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'BBB'" />
</xsl:otherwise>
</xsl:choose>

Nesting of xsl:when conditions

I have a query related to xsl choose , inside xsl choose is being used
Now i have two xsl:when condition is there like as hsown below
<xsl:choose>
<xsl:when test=$labcVar=$cde>
<xsl:when test="$erf=$der">
<xsl:value-of select="'edr'" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'fre'" />
</xsl:otherwise>
please advise is it the correct approach since insise xsl:when ..I have to begain only when first when condition becomes true the only I should go for second xsl:when condition, please advsie it is aloowed or not
You can't nest a when directly inside a when, but you can use another choose:
<xsl:choose>
<xsl:when test=$labcVar=$cde>
<xsl:choose>
<xsl:when test="$erf=$der">
<xsl:value-of select="'edr'" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'fre'" />
</xsl:otherwise>
</xsl:choose>
</xsl:when>
</xsl:choose>
How about using and
<xsl:when test="$labcVar=$cde and $erf=$der">
<xsl:value-of select="'edr'" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'fre'" />
</xsl:otherwise>