Question

I have this XSLT:

<xsl:template match="/">

    <xsl:variable name="errorCount" select="count($orders/*[1]/cm:Error)" />

    <xsl:apply-templates select="@*|node()">
        <xsl:with-param name="errorCount" select="$errorCount" tunnel="yes" />
    </xsl:apply-templates>
</xsl:template>

<xsl:template match="status">
    <xsl:param name="errorCount" tunnel="yes" />
    <xsl:copy>
        <xsl:choose>
            <xsl:when test="$errorCount > 0">
                <xsl:text>ERROR</xsl:text>
            </xsl:when>
            <xsl:otherwise>
                <xsl:text>OK</xsl:text>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:copy>
</xsl:template>

The tunneling and all seems to work, but the transformation fails with the following error:

Required item type of first operand of '>' is numeric; supplied value has item type xs:string

I first had the variable declaration in the template where it is it used, and then it worked fine. Moved it because I need to use the same count in other templates too.

How/Where do I declare that this variable/parameter is in fact a number?

Was it helpful?

Solution

Since you are using XSLT 2.0, then you should also add an as attribute to your xsl:param in the template. For example (you may have to use a different as value depending on what you need the resulting number to be, such as if you'll have values that have decimals; you would also need to correct the tunnel value, per Michael Kay's point):

<xsl:param name="errorCount" tunnel="yes" as="xs:integer" />

The transform would fail if it couldn't be converted to the as type (in this case, an integer). Eero's solution may look cleaner because you'll still have to check to see if the value is greater than zero. But, because you are using XSLT 2.0, the best practice is to type your parameters/variables.

OTHER TIPS

You can use number() to convert a string to a number:

<xsl:when test="number($errorCount) > 0">
  <xsl:text>ERROR</xsl:text>
</xsl:when>

My suspicion is that because you wrote tunnel="true" rather than tunnel="yes", the fact that you specified tunnel at all is being (incorrectly) ignored, and the parameter is being given its default value, which is a zero-length string.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top