9

I want a variable to have the value of an element if the value is numeric, but if it's not then I want the variable to have the value 0.

In other words, is there a simple equivalent of the following in XSLT?

var foobar = is_numeric(element value) ? element value : 0

Or how would you write this?

<xsl:variable name="foobar" select=" ? " />
Svish
  • 145,946
  • 169
  • 443
  • 600

3 Answers3

16

XPath 1.0:

<xsl:variable name="foobar">
  <xsl:choose>
    <xsl:when test="number($value) = number($value)">
      <xsl:value-of select="$value"/>
    </xsl:when>
    <xsl:otherwise>0</xsl:otherwise>
  </xsl:choose>
</xsl:variable>

Reference for this clever number($value) = number($value) numeric test: Dimitre Novatchev's answer to "Xpath test if is number" question.

Community
  • 1
  • 1
kjhughes
  • 98,039
  • 18
  • 159
  • 218
10

In XPath 2.0 yes, you can use "castable as"

<xsl:variable name="foobar" as="xs:double"
   select="if (x castable as xs:double) then x else 0" />
Svish
  • 145,946
  • 169
  • 443
  • 600
Ian Roberts
  • 117,925
  • 15
  • 163
  • 179
6

You could use:

<xsl:variable name="x" 
              select="(ELEMENT[. castable as xs:double], 0)[1]"/>

or

<xsl:variable name="x" 
              select="sum(ELEMENT[. castable as xs:double])"/>
Michael Kay
  • 147,186
  • 10
  • 83
  • 148
  • What does `(x, y)` do, in your first example? – Svish Oct 03 '13 at 08:03
  • 1
    @Svish, `(x, y)` forms a sequence of `x` and `y` but as `ELEMENT[. castable as xs:double]` yields the empty sequence if the content of `ELEMENT` is not a double the value is either a sequence of `(ELEMENT, 0)` or simply the sequence `(0)`. And the predicate `[1]` then selects `ELEMENT` or `0`. – Martin Honnen Oct 03 '13 at 09:02
  • @Svish so in particular if there is more than one `ELEMENT` child in the current context then my approach will always return `0` (because a sequence of more than one item is not `castable as xs:double`), whereas Michael's approach will return the first `ELEMENT` child which can be cast to `xs:double` (in the `(x, y)[1]` case) or the sum of all such `ELEMENT`s (in the `sum()` case), or `0` if none of them are appropriately castable. – Ian Roberts Oct 03 '13 at 09:09
  • Cool, thanks for the explanations. I'm going for @IanRoberts since that expresses most clearly what I actually want. Seems less hackish, hehe. – Svish Oct 04 '13 at 11:59