tags:

views:

87

answers:

4

I have to create an xsl variable with a choose in it. Like the following:

<xsl:variable name="grid_position">
  <xsl:choose>
    <xsl:when test="count(/Element) &gt;= 1">
      inside
    </xsl:when>
    <xsl:otherwise>
      outside
    </xsl:otherwise>
  </xsl:choose>
</xsl:variable>

And later in my code, I do an xsl if:

<xsl:if test="$grid_position = 'inside'">
   {...code...}
</xsl:if>

Problem is that my variable is never = 'inside' because of the line breaks and indent. How can I remove whitespaces from my variable? I know I can remove it using disable-output-escaping="yes" when I use it in a xsl:copy-of, but it's not working on the xsl:variable tag. So how can I remove those whitespace and line breaks?

+5  A: 

The simplest way is not to put the whitespace there in the first place:

<xsl:variable name="grid_position">
  <xsl:choose>
    <xsl:when test="count(/Element) &gt;= 1">inside</xsl:when>
    <xsl:otherwise>outside</xsl:otherwise>
  </xsl:choose>
</xsl:variable>
Jim Garrison
+1 simplest fix.
Tomalak
@Jim Garrison: +1 for simplest way
Alejandro
@Jim Garrison: Thank you for your answer, but I went with Tomalak's answer because I don't want my code to break if someone reformat the xsl code to add a line break.
Gabriel
@Gabriel: You did the right thing. Tomalak's answer is more general.
Jim Garrison
+7  A: 

That's what <xsl:text> is for:

<xsl:variable name="grid_position">
  <xsl:choose>
    <xsl:when test="count(/Element) &gt;= 1">
      <xsl:text>inside</xsl:text>
    </xsl:when>
    <xsl:otherwise>
      <xsl:text>outside</xsl:text>
    </xsl:otherwise>
  </xsl:choose>
</xsl:variable>

It allows you to structure your code and control whitespace at the same time.

In fact, you should stay clear of text nodes in XSL that are not wrapped in <xsl:text> to avoid these kinds of bugs in the future, too (i.e. when code gets re-formatted or re-factored later).

For simple cases, like in your sample, doing what Jim Garrison suggests is also an option.


As an aside, testing for the existence of an element with count() is superfluous. Selecting it is enough, since the empty node-set evaluates to false.

<xsl:when test="/Element">
Tomalak
Thank you for this solution Tomalak, it's working perfectly!
Gabriel
@Gabriel: You are welcome. :)
Tomalak
@Tomalak: +1 for explanation of node set's boolean value
Alejandro
+3  A: 

Just use:

<xsl:variable name="grid_position" select=
 "concat(substring('inside', 1 div boolean(/Element)),
         substring('outside', 1 div not(/Element))
        )
 "/>
Dimitre Novatchev
@Dimitre: +1 for one line expression
Alejandro
+1 for this great tip. I often miss the "? :" ternary operator of C/Java/JavaScript.
dolmen
+2  A: 

The strategies in the other answers are good, in fact preferable to this one when feasible. But there are times when you don't have control over (or it's harder to control) what's in the variable. In those cases, you can strip away the surrounding space when you're testing the variable:

Instead of

<xsl:if test="$grid_position = 'inside'">

use

<xsl:if test="normalize-space($grid_position) = 'inside'">

normalize-space() strips the leading and trailing whitespace, and collapses other repeating white spaces to single ones.

LarsH
+1 That's the obvious answer that has been missing so far. Storing surplus whitespace and then stripping it again is not elegant, but sometimes there is no way around it, e.g. when you have no influence on the XML.
Tomalak